initial checkin of libc source and tests

This commit is contained in:
gdr 1997-02-28 05:12:58 +00:00
parent cb5fd8e82d
commit 596add410c
98 changed files with 14068 additions and 0 deletions

19
lib/libc/Contributers Normal file
View File

@ -0,0 +1,19 @@
List of Contributers
====================
$Id: Contributers,v 1.1 1997/02/28 05:12:39 gdr Exp $
The following people and organizations have contributed, knowingly or
otherwise, to the code in this library. Some other contributions were
necessarily anonymous, as they were derived from code fragments for which
no author information was available:
Jawaid Bazyar
Soenke Behrens
Douglas Gwyn
Devin Reade
Derek Taubert
Phillip Vandry
The Byte Works, Inc.
University of California, Berkeley.

59
lib/libc/Makefile Normal file
View File

@ -0,0 +1,59 @@
#
# This is the top-level makefile for libc, GNO v2.0.6
#
# dmake is too bloated right now to due recursive makes well, so before
# you run make in this directory, ensure you run make in the following
# directories:
# gen, gno, locale, stdio, stdlib, string, sys
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:39 gdr Exp $
#
.INCLUDE: ../const.mk
LIBC_OBJ = \
sys/exec.o \
sys/syscall.o \
sys/trap.o \
gno/gnocmd.o \
gno/gnomisc.o \
gno/gsstring.o \
gno/map.o \
gno/parsearg.o \
gno/stack.o \
gen/basename.o \
gen/bmem.o \
gen/compat.o \
gen/crypt.o \
gen/crypta.o \
gen/dirent.o \
gen/err.o \
gen/fnmatch.o \
gen/getcwd.o \
gen/getgrent.o \
gen/getpass.o \
gen/getpwent.o \
gen/getttyent.o \
gen/hostname.o \
gen/oldlog.o \
gen/popen.o \
gen/pwcache.o \
gen/scandir.o \
gen/setjmp.o \
gen/sleep.o \
gen/syslog.o \
gen/tty.o \
gen/utime.o \
locale/table.o \
stdio/mktemp.o \
stdio/perror.o \
stdio/tempnam.o \
stdlib/environ.o \
stdlib/getopt.o \
stdlib/getsubopt.o \
string/case.o \
string/str.o
libc: $(LIBC_OBJ)
$(RM) -f $@
$(MAKELIB) $(MAKELIBFLAGS) -l $@ $(LIBC_OBJ)

21
lib/libc/gen/Makefile Normal file
View File

@ -0,0 +1,21 @@
#
# Makefile for libc/gen.
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:43 gdr Exp $
#
.INCLUDE: ../../const.mk
OBJ_ASM = crypta.o setjmp.o syslog.o
OBJ_C = basename.o bmem.o compat.o crypt.o dirent.o err.o fnmatch.o getcwd.o \
getgrent.o getpass.o getpwent.o getttyent.o hostname.o oldlog.o \
popen.o pwcache.o scandir.o sleep.o tty.o utime.o
NOT_YET = fts.o
OBJS = $(OBJ_ASM) $(OBJ_C)
default: $(OBJS)
asm: $(OBJ_ASM)
c: $(OBJ_C)
.INCLUDE: ../rules.mk

82
lib/libc/gen/basename.c Normal file
View File

@ -0,0 +1,82 @@
/*
* These routines were written by Devin Reade for GNO v2.0.4.
*
* $Id: basename.c,v 1.1 1997/02/28 05:12:43 gdr Exp $
*
* This file is formatted for tabs every 8 columns.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <string.h>
#include <stdio.h>
#include <unistd.h>
/*
* basename
*
* returns the filename component of <path>. If <path> contains colons,
* they are assumed to be the directory separators, otherwise any '/' is
* assumed to be a directory separator.
*
* If no directory separators are found, then the full path is returned.
*
* No check is done as to whether the pathname is valid on the any
* given filesystem.
*/
char *
basename (const char *path) {
char delim, *p;
delim = strchr(path,':') ? ':' : '/';
p = strrchr(path,delim);
return p ? p+1 : path;
}
/*
* dirname
*
* Returns a pointer to an internal buffer that contains a string that
* matches the directory component
* of <path>. If <path> contains at least one ':', then it is assumed
* that colons are directory separators, otherwise any '/' character
* is treated as a directory separator.
*
* If <path> contains no pathname separators, then dirname() will
* return an empty (zero-length) string.
*
* No check is done as to whether the pathname is valid on the any
* given filesystem.
*/
char *
dirname (const char *path)
{
char delim, *p;
size_t len;
static char dir[PATH_MAX];
len = strlen(path);
if (len >= PATH_MAX) {
len = PATH_MAX -1;
strncpy(dir,path,len);
dir[len] = '\0';
} else {
strcpy(dir, path);
}
delim = strchr(dir,':') ? ':' : '/';
p = strrchr(dir,delim);
if (p == NULL) {
*dir = '\0';
} else {
*p = '\0';
}
return dir;
}

25
lib/libc/gen/bmem.c Normal file
View File

@ -0,0 +1,25 @@
/*
* $Id: bmem.c,v 1.1 1997/02/28 05:12:43 gdr Exp $
*
* This file is formatted with tabs every 8 columns.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <string.h>
void
bzero(void *buf, size_t len) {
memset(buf, 0, len);
}
void
bcopy(const void *src, const void *dest, size_t len) {
memmove(dest, src, len);
}

29
lib/libc/gen/compat.c Normal file
View File

@ -0,0 +1,29 @@
/*
* These functions really belong in a separate library, libcompat, if
* we're trying to be BSD-ish. They are all obsolete functions.
*
* $Id: compat.c,v 1.1 1997/02/28 05:12:43 gdr Exp $
*
* This file is formatted with tabs every 8 characters.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <sgtty.h>
int
gtty(int filedes, struct sgttyb *argp) {
return ioctl(filedes,TIOCGETP,argp);
}
int
stty (int filedes, struct sgttyb *argp) {
return ioctl(filedes,TIOCSETP,argp);
}

336
lib/libc/gen/crypt.c Normal file
View File

@ -0,0 +1,336 @@
/*
* From Andy Tanenbaum's book "Computer Networks", rewritten in C.
*
* Many performance modifications made
* January 19-22, 1992 by Jawaid Bazyar
* Copyright 1992-1997, Procyon Inc.
*
* $Id: crypt.c,v 1.1 1997/02/28 05:12:43 gdr Exp $
*
* This file is formatted with tab stops every 8 columns.
*/
#ifdef __ORCAC__
/* segment "libc_gen__"; *//* don't segment this until crypt.asm is done */
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <stdlib.h>
#include <string.h>
/* These symbols have been moved to or are referenced from crypta.asm */
#ifndef NOTDEFINED
#define f(i,key,a,x) __crypt_f(i, key, a, x)
#define transpose(data,t,n) __crypt_transpose(data, t, n)
#define rotate(key) __crypt_rotate(key)
#define s_boxes __crypt_s_boxes
#define rots __crypt_rots
#endif
struct block {
unsigned char b_data[64];
};
struct ordering {
unsigned char o_data[64];
};
static struct block key; /* gdr added "static" */
static struct ordering InitialTr = {
58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,
62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,
57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,
61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7,
};
static struct ordering FinalTr = {
40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,
38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,
36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,
34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25,
};
static struct ordering swap = {
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
};
static struct ordering KeyTr1 = {
57,49,41,33,25,17, 9, 1,58,50,42,34,26,18,
10, 2,59,51,43,35,27,19,11, 3,60,52,44,36,
63,55,47,39,31,23,15, 7,62,54,46,38,30,22,
14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4,
};
struct ordering KeyTr2 = {
14,17,11,24, 1, 5, 3,28,15, 6,21,10,
23,19,12, 4,26, 8,16, 7,27,20,13, 2,
41,52,31,37,47,55,30,40,51,45,33,48,
44,49,39,56,34,53,46,42,50,36,29,32,
};
static struct ordering etr = {
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
8, 9,10,11,12,13,12,13,14,15,16,17,
16,17,18,19,20,21,20,21,22,23,24,25,
24,25,26,27,28,29,28,29,30,31,32, 1,
};
struct ordering ptr = {
16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10,
2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25,
};
char s_boxes[8][64] = {
{ 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
},
{ 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
},
{ 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
},
{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
},
{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
},
{ 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
},
{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
},
{ 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
},
};
int rots[] = {
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
};
/* transpose, rotate, and f were rewritten in assembly- see crypta.asm */
#ifndef NOTDEFINED
void __crypt_f __P((int i, struct block *key, struct block *a, struct block *x));
void __crypt_transpose __P((struct block *data, struct ordering *t, int n));
void __crypt_rotate __P((struct block *key));
#else
static
transpose(data, t, n)
register struct block *data;
register struct ordering *t;
register int n;
{
struct block x;
memcpy(&x,data,sizeof(struct block));
/* x = *data; you can't do that in C!!! */
while (n-- > 0) {
data->b_data[n] = x.b_data[t->o_data[n] - 1];
}
}
static
rotate(key)
register struct block *key;
{
register unsigned char *p = key->b_data;
register unsigned char *ep = &(key->b_data[55]);
int data0 = key->b_data[0], data28 = key->b_data[28];
while (p++ < ep) *(p-1) = *p;
key->b_data[27] = data0;
key->b_data[55] = data28;
}
#endif
struct ordering *EP = &etr;
#ifdef NOTDEFINED
static
f(i, key, a, x)
struct block *key, *a;
register struct block *x;
{
struct block e, ikey, y;
int k;
register unsigned char *p, *q, *r;
memcpy(&e,a,sizeof(struct block));
/* e = *a; */
transpose(&e, EP, 48);
for (k = rots[i]; k; k--) rotate(key);
memcpy(&ikey,key,sizeof(struct block));
/* ikey = *key; */
transpose(&ikey, &KeyTr2, 48);
p = &(y.b_data[48]);
q = &(e.b_data[48]);
r = &(ikey.b_data[48]);
while (p > y.b_data) {
*--p = *--q ^ *--r;
}
q = x->b_data;
for (k = 0; k < 8; k++) {
register int xb, r;
r = *p++ << 5;
r += *p++ << 3;
r += *p++ << 2;
r += *p++ << 1;
r += *p++;
r += *p++ << 4;
xb = s_boxes[k][r];
*q++ = (xb >> 3) & 1;
*q++ = (xb>>2) & 1;
*q++ = (xb>>1) & 1;
*q++ = (xb & 1);
}
transpose(x, &ptr, 32);
}
#endif
void
setkey(register const char *k)
{
key = *((struct block *) k);
transpose(&key, &KeyTr1, 56);
}
void
encrypt(char *blck, int edflag)
{
register struct block *p = (struct block *) blck;
register int i;
transpose(p, &InitialTr, 64);
for (i = 15; i>= 0; i--) {
int j = edflag ? i : 15 - i;
register int k;
struct block b, x;
memcpy(&b,p,sizeof(struct block));
/* b = *p; */
for (k = 31; k >= 0; k--) {
p->b_data[k] = b.b_data[k + 32];
}
f(j, &key, p, &x);
for (k = 31; k >= 0; k--) {
p->b_data[k+32] = b.b_data[k] ^ x.b_data[k];
}
}
transpose(p, &swap, 64);
transpose(p, &FinalTr, 64);
}
char *
crypt(register const char *pw, const char *salt)
{
/* Unfortunately, I had to look at the sources of V7 crypt.
There was no other way to find out what this routine
actually does.
*/
char pwb[66];
static char result[16];
register char *p = pwb;
struct ordering new_etr;
register int i;
char *pw2;
while (*pw && p < &pwb[64]) {
register int j = 7;
while (j--) {
*p++ = (*pw >> j) & 01;
}
pw++;
*p++ = 0;
}
while (p < &pwb[64]) *p++ = 0;
setkey(p = pwb);
while (p < &pwb[66]) *p++ = 0;
new_etr = etr;
EP = &new_etr;
for (i = 0; i < 2; i++) {
register char c = *salt++;
register int j;
result[i] = c;
if ( c > 'Z') c -= 6 + 7 + '.'; /* c was a lower case letter */
else if ( c > '9') c -= 7 + '.';/* c was upper case letter */
else c -= '.'; /* c was digit, '.' or '/'. */
/* now, 0 <= c <= 63 */
for (j = 0; j < 6; j++) {
if ((c >> j) & 01) {
int t = 6*i + j;
int temp = new_etr.o_data[t];
new_etr.o_data[t] = new_etr.o_data[t+24];
new_etr.o_data[t+24] = temp;
}
}
}
if (result[1] == 0) result[1] = result[0];
for (i = 0; i < 25; i++) encrypt(pwb,0);
EP = &etr;
p = pwb;
pw2 = result+2;
while (p < &pwb[66]) {
register int c = 0;
register int j = 6;
while (j--) {
c <<= 1;
c |= *p++;
}
c += '.'; /* becomes >= '.' */
if (c > '9') c += 7; /* not in [./0-9], becomes upper */
if (c > 'Z') c += 6; /* not in [A-Z], becomes lower */
*pw2++ = c;
}
*pw2 = 0;
return result;
}

268
lib/libc/gen/crypta.asm Normal file
View File

@ -0,0 +1,268 @@
*
* Performance modifications to crypt.c routines.
* 19-22 January 1992 by Jawaid Bazyar
* Copyright 1992, Procyon Inc.
*
* $Id: crypta.asm,v 1.1 1997/02/28 05:12:43 gdr Exp $
*
* Because of the four storage blocks listed below (copyOfData, e, ikey, and
* yb), this doesn't seem to be compatible with the large memory model.
* This should be changed. These routines should also be placed in the
* libc_gen__ load segment.
*
mcopy crypta.mac
case on
* void __crypt_transpose (struct block *data, struct ordering *t, int n);
__crypt_transpose START
subroutine (2:n,4:t,4:data),2
ldy #62
lp lda [data],y
sta copyOfData,y
dey2
bpl lp
lda #0 ; clear out hi-byte of A
short m
lp2 ldy n
beq donelp2
dec n
ldy n
lda [t],y
dec a
tay
lda copyOfData,y
ldy n
sta [data],y
bra lp2
donelp2 long m
return
copyOfData ds 64
END
* void __crypt_rotate (struct block *key);
__crypt_rotate START
data0 equ 0
data28 equ 2
ep equ 4
subroutine (4:key),6
lda #55
sta ep
short m
lda [key]
sta data0
ldy #28
lda [key],y
sta data28
ldy #0
lp cpy ep
bcs donelp
iny
lda [key],y
dey
sta [key],y
iny
bra lp
donelp lda data0
ldy #27
sta [key],y
lda data28
ldy #55
sta [key],y
long m
return
END
* void __crypt_f (int i, struct block *key, struct block *a, struct block *x);
__crypt_f START
k equ 0
p equ 2
q equ 4
r equ 6
xb equ 8
subroutine (4:x,4:a,4:key,2:i),10
ldy #62
lp1 lda [a],y
sta e,y
dey2
bpl lp1
ph2 #48
ph4 __crypt_EP
ph4 #e
jsl transpose
lda i
asl a
tay
lda __crypt_rots,y
sta k
lp2 lda k
beq donelp2
ph4 key
jsl rotate
dec k
bra lp2
donelp2 anop
ldy #62
lp3 lda [key],y
sta ikey,y
dey2
bpl lp3
ph2 #48
ph4 #KeyTr2
ph4 #ikey
jsl transpose
short m
ldy #48
lp4 cpy #0
beq donelp4
dey
lda e,y
eor ikey,y
sta yb,y
bra lp4
donelp4 anop
long m
ldy #0
stz p
stz q
stz k
kloop lda k
cmp #8
bcc okay
jmp donekloop
okay ldy p
lda yb,y
iny
and #$FF
asl a
asl a
asl a
asl a
asl a
sta r
lda yb,y
iny
and #$FF
asl a
asl a
asl a
clc
adc r
sta r
lda yb,y
iny
and #$FF
asl a
asl a
clc
adc r
sta r
lda yb,y
iny
and #$FF
asl a
clc
adc r
sta r
lda yb,y
iny
and #$FF
clc
adc r
sta r
lda yb,y
iny
and #$FF
asl a
asl a
asl a
asl a
clc
adc r
sta r
sty p ; store it temporarily
lda k
asl a
asl a
asl a
asl a
asl a
asl a ; k * 64
clc
adc r ; + r;
tay
lda __crypt_s_boxes,y
and #$FF
sta xb
* *q++ = (xb >> 3) & 1;
ldy q
lda xb
lsr a
lsr a
lsr a
and #1
short m
sta [x],y
long m
iny
* *q++ = (xb >> 2) & 1;
lda xb
lsr a
lsr a
and #1
short m
sta [x],y
long m
iny
* *q++ = (xb >> 1) & 1
lda xb
lsr a
and #1
short m
sta [x],y
long m
iny
* *q++ = xb & 1;
lda xb
and #1
short m
sta [x],y
long m
iny
sty q
inc k
jmp kloop
donekloop anop
ph2 #32
ph4 #ptr
ph4 x
jsl transpose
return
e ds 64
ikey ds 64
yb ds 64
END

249
lib/libc/gen/crypta.mac Normal file
View File

@ -0,0 +1,249 @@
MACRO
&lab subroutine &parms,&work
&lab anop
aif c:&work,.a
lclc &work
&work setc 0
.a
gbla &totallen
gbla &worklen
&worklen seta &work
&totallen seta 0
aif c:&parms=0,.e
lclc &len
lclc &p
lcla &i
&i seta c:&parms
.b
&p setc &parms(&i)
&len amid &p,2,1
aif "&len"=":",.c
&len amid &p,1,2
&p amid &p,4,l:&p-3
ago .d
.c
&len amid &p,1,1
&p amid &p,3,l:&p-2
.d
&p equ &totallen+3+&work
&totallen seta &totallen+&len
&i seta &i-1
aif &i,^b
.e
tsc
sec
sbc #&work
tcs
inc a
phd
tcd
phb
phk
plb
mend
MACRO
&lab return &r
&lab anop
lclc &len
aif c:&r,.a
lclc &r
&r setc 0
&len setc 0
ago .h
.a
&len amid &r,2,1
aif "&len"=":",.b
&len amid &r,1,2
&r amid &r,4,l:&r-3
ago .c
.b
&len amid &r,1,1
&r amid &r,3,l:&r-2
.c
aif &len<>2,.d
ldy &r
ago .h
.d
aif &len<>4,.e
ldx &r+2
ldy &r
ago .h
.e
aif &len<>10,.g
ldy #&r
ldx #^&r
ago .h
.g
mnote 'Not a valid return length',16
mexit
.h
aif &totallen=0,.i
lda &worklen+1
sta &worklen+&totallen+1
lda &worklen
sta &worklen+&totallen
.i
plb
pld
tsc
clc
adc #&worklen+&totallen
tcs
aif &len=0,.j
tya
.j
rtl
mend
MACRO
&lab short &stat
&lab anop
lcla &t
lcla &len
lclc &ch
&t seta 0
&len seta l:&stat
.a
aif &len=0,.b
&ch amid &stat,&len,1
aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i
aif ("&ch"="a").or.("&ch"="m"),.m
.c
&len seta &len-1
ago ^a
.i
longi off
&t seta &t+16
ago ^c
.m
longa off
&t seta &t+32
ago ^c
.b
aif &t=0,.d
sep #&t
.d
mend
MACRO
&lab dey2
&lab dey
dey
mend
MACRO
&lab long &stat
&lab anop
lcla &t
lcla &len
lclc &ch
&t seta 0
&len seta l:&stat
.a
aif &len=0,.b
&ch amid &stat,&len,1
aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i
aif ("&ch"="a").or.("&ch"="m"),.m
.c
&len seta &len-1
ago ^a
.i
longi on
&t seta &t+16
ago ^c
.m
longa on
&t seta &t+32
ago ^c
.b
aif &t=0,.d
rep #&t
.d
mend
macro
&lab ph4 &n1
aif "&n1"="*",.f
lclc &c
&lab anop
&c amid &n1,1,1
aif "&c"="#",.d
aif s:longa=1,.a
rep #%00100000
.a
aif "&c"<>"{",.b
&c amid &n1,l:&n1,1
aif "&c"<>"}",.g
&n1 amid &n1,2,l:&n1-2
ldy #2
lda (&n1),y
pha
lda (&n1)
pha
ago .e
.b
aif "&c"<>"[",.c
ldy #2
lda &n1,y
pha
lda &n1
pha
ago .e
.c
aif "&c"<>"<",.c1
&n1 amid &n1,2,l:&n1-1
pei &n1+2
pei &n1
ago .e
.c1
lda &n1+2
pha
lda &n1
pha
ago .e
.d
&n1 amid &n1,2,l:&n1-1
pea +(&n1)|-16
pea &n1
ago .f
.e
aif s:longa=1,.f
sep #%00100000
.f
mexit
.g
mnote "Missing closing '}'",16
mend
MACRO
&lab ph2 &parm
lclc &char
&lab anop
aif c:&parm=0,.done
&char amid &parm,1,1
aif "&char"="#",.immediate
aif "&char"="@",.at
aif s:longa=1,.chk
rep #%00100000
.chk
aif "&char"<>"{",.absolute
&char amid &parm,l:&parm,1
aif "&char"<>"}",.error
&parm amid &parm,2,l:&parm-2
lda (&parm)
pha
ago .shorten
.absolute
lda &parm
pha
ago .shorten
.immediate
&parm amid &parm,2,l:&parm-1
pea &parm
ago .done
.at
&char amid &parm,2,1
ph&char
.shorten
aif s:longa=1,.done
sep #%00100000
.done
mexit
.error
mnote "Missing closing '}'",16
mend

179
lib/libc/gen/dirent.c Normal file
View File

@ -0,0 +1,179 @@
/*
* The original version of these routines (for GNO v2.0.5 and earlier)
* were by Derek Taubert and Jawaid Bazyar. Reimplemented from scratch
* by Devin Reade.
*
* $Id: dirent.c,v 1.1 1997/02/28 05:12:43 gdr Exp $
*
* This file is formatted with tab stops every 8 characters.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#define __LIBC_DIRENT /* needed for decls in <dirent.h> */
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <gsos.h>
#include <dirent.h>
#include <errno.h>
#include <gno/gno.h>
DIR *
opendir (char *filename) {
DIR *dirp;
OpenRecGS *openRecPtr;
int err;
/*
* the original version of this code used an ExpandDevices call
* to expand filename before the call to OpenGS
*/
/* do the allocations */
if ((dirp = malloc(sizeof(DIR))) == NULL) {
return NULL;
}
if ((dirp->dd_ent = malloc(sizeof(DirEntryRecGS))) == NULL) {
free(dirp);
return NULL;
}
if ((dirp->dd_ent->name = (ResultBuf255Ptr) GOinit (255, NULL))
== NULL) {
free(dirp->dd_ent);
free(dirp);
return NULL;
}
if ((dirp->dd_data = malloc(sizeof(struct dirent))) == NULL) {
free(dirp->dd_ent->name);
free(dirp->dd_ent);
free(dirp);
return NULL;
}
if ((openRecPtr = malloc(sizeof(OpenRecGS))) == NULL) {
free(dirp->dd_data);
free(dirp->dd_ent->name);
free(dirp->dd_ent);
free(dirp);
return NULL;
}
if ((openRecPtr->pathname = (GSString255Ptr) __C2GSMALLOC(filename))
== NULL) {
free(openRecPtr);
free(dirp->dd_data);
free(dirp->dd_ent->name);
free(dirp->dd_ent);
free(dirp);
return NULL;
}
/* open what is believed to be a directory */
openRecPtr->pCount = 8;
openRecPtr->requestAccess = readEnable;
openRecPtr->resourceNumber = 0;
OpenGS(openRecPtr);
if ((err = _mapErr(_toolErr)) == 0) {
if (openRecPtr->storageType != 0x0d && /* subdirectory */
openRecPtr->storageType != 0x0f) { /* volume directory */
err = ENOTDIR;
openRecPtr->pCount = 1;
CloseGS(openRecPtr); /* cheat a bit */
}
}
if (err) {
free(openRecPtr->pathname);
free(openRecPtr);
free(dirp->dd_data);
free(dirp->dd_ent->name);
free(dirp->dd_ent);
free(dirp);
errno = err;
return NULL;
}
/* if we're here, filename has been opened and it's a directory */
dirp->dd_fd = openRecPtr->refNum;
dirp->dd_ent->pCount = 7;
dirp->dd_ent->refNum = dirp->dd_fd;
free(openRecPtr->pathname);
free(openRecPtr);
return dirp;
}
struct dirent *
readdir (DIR *dirp) {
struct dirent *result;
int err;
/* get the info from GS/OS */
dirp->dd_ent->base = 1;
dirp->dd_ent->displacement = 1;
GetDirEntryGS(dirp->dd_ent);
if ((err = _mapErr(_toolErr)) != 0) {
return NULL;
}
/* copy it into the user-usable buffer */
result = dirp->dd_data;
result->d_fileno = dirp->dd_ent->entryNum;
result->d_reclen = sizeof(struct dirent);
switch (dirp->dd_ent->fileType) {
case 0x0f:
result->d_type = DT_DIR;
default:
result->d_type = DT_REG;
}
result->d_namlen = (char) dirp->dd_ent->name->bufString.length;
memcpy(result->d_name, dirp->dd_ent->name->bufString.text,
(size_t) result->d_namlen);
result->d_name[result->d_namlen] = '\0';
return result;
}
void
rewinddir (DIR *dirp) {
dirp->dd_ent->base = 0;
dirp->dd_ent->displacement = 0;
GetDirEntryGS(dirp->dd_ent);
}
long
telldir (DIR *dirp) {
return (long) dirp->dd_ent->entryNum;
}
void
seekdir (DIR *dirp, long loc) {
dirp->dd_ent->base = 0;
dirp->dd_ent->displacement = loc;
GetDirEntryGS(dirp->dd_ent);
}
int
closedir (DIR *dirp) {
int closerec[2];
int err;
closerec[0] = 1;
closerec[1] = dirp->dd_ent->refNum;
CloseGS(closerec);
err = _mapErr(_toolErr);
free(dirp->dd_data);
free(dirp->dd_ent->name);
free(dirp->dd_ent);
free(dirp);
if (err) {
errno = err;
return -1;
} else {
return 0;
}
}

187
lib/libc/gen/err.c Normal file
View File

@ -0,0 +1,187 @@
/*
* This file is formatted with tab stops every 8 columns.
*
* $Id: err.c,v 1.1 1997/02/28 05:12:43 gdr Exp $
*/
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma memorymodel 0
/* need bit 3 for variadic function definitions */
#pragma optimize 8
#pragma debug 0
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <gno/gno.h>
/*
* 4.4BSD uses __progname of type char *. That requires having access
* to the compiler startup code. We use __prognameGS() to get us that
* information from GS/OS.
*/
static FILE *err_file = NULL; /* file to use for error output */
static void (*err_exit)(int) = NULL;
void err_set_file(void *fp);
void err_set_exit(void (*ef)(int));
void
err_set_file(void *fp)
{
if (fp) {
err_file = fp;
} else {
err_file = stderr;
}
}
void
err_set_exit(void (*ef)(int))
{
err_exit = ef;
}
volatile void
err(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verr(eval, fmt, ap);
va_end(ap);
}
volatile void
verr(int eval, const char *fmt, va_list ap)
{
int sverrno;
sverrno = errno;
if (! err_file) {
err_set_file((FILE *)0);
}
fprintf(err_file, "%s: ", __prognameGS());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
fprintf(err_file, ": ");
}
fprintf(err_file, "%s\n", strerror(sverrno));
if(err_exit) {
err_exit(eval);
}
exit(eval);
}
volatile void
errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrx(eval, fmt, ap);
va_end(ap);
}
volatile void
verrx(int eval, const char *fmt, va_list ap)
{
if (! err_file) {
err_set_file((FILE *)0);
}
fprintf(err_file, "%s: ", __prognameGS());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
}
fprintf(err_file, "\n");
if (err_exit) {
err_exit(eval);
}
exit(eval);
}
void
warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarn(fmt, ap);
va_end(ap);
}
void
vwarn(const char *fmt, va_list ap)
{
int sverrno;
sverrno = errno;
if (! err_file) {
err_set_file((FILE *)0);
}
fprintf(err_file, "%s: ", __prognameGS());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
fprintf(err_file, ": ");
}
fprintf(err_file, "%s\n", strerror(sverrno));
}
void
warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
void
vwarnx(const char *fmt, va_list ap)
{
if (! err_file) {
err_set_file((FILE *)0);
}
fprintf(err_file, "%s: ", __prognameGS());
if (fmt != NULL) {
vfprintf(err_file, fmt, ap);
}
fprintf(err_file, "\n");
}

257
lib/libc/gen/fnmatch.c Normal file
View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This implementation uses recursion. It should be rewritten to avoid
* it due to stack limitations on the IIgs.
*
* $Id: fnmatch.c,v 1.1 1997/02/28 05:12:44 gdr Exp $
*
* This file is formatted for tab stops every 8 characters.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
#endif /* LIBC_SCCS and not lint */
/*
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
* Compares a filename or pathname to a pattern.
*/
#include <fnmatch.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <err.h>
#define EOS '\0'
static const char *rangematch __P((const char *, int, int));
static void _fnmatch_map (const char *, const char *, char **, char **, int);
int
fnmatch(const char *opattern, const char *ostring, int flags)
{
const char *stringstart;
char c, test;
char *pattern, *string;
_fnmatch_map(ostring, opattern, &string, &pattern, flags);
for (stringstart = string;;)
switch (c = *pattern++) {
case EOS:
return (*string == EOS ? 0 : FNM_NOMATCH);
case '?':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
++string;
break;
case '*':
c = *pattern;
/* Collapse multiple stars. */
while (c == '*')
c = *++pattern;
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
/* Optimize for pattern with * at end or before /. */
if (c == EOS)
if (flags & FNM_PATHNAME)
return (strchr(string, '/') == NULL ?
0 : FNM_NOMATCH);
else
return (0);
else if (c == '/' && flags & FNM_PATHNAME) {
if ((string = strchr(string, '/')) == NULL)
return (FNM_NOMATCH);
break;
}
/* General case, use recursion. */
while ((test = *string) != EOS) {
if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
return (0);
if (test == '/' && flags & FNM_PATHNAME)
break;
++string;
}
return (FNM_NOMATCH);
case '[':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && flags & FNM_PATHNAME)
return (FNM_NOMATCH);
if ((pattern =
rangematch(pattern, *string, flags)) == NULL)
return (FNM_NOMATCH);
++string;
break;
case '\\':
if (!(flags & FNM_NOESCAPE)) {
if ((c = *pattern++) == EOS) {
c = '\\';
--pattern;
}
}
/* FALLTHROUGH */
default:
if (c != *string++)
return (FNM_NOMATCH);
break;
}
/* NOTREACHED */
}
static const char *
rangematch(const char *pattern, int test, int flags)
{
int negate, ok;
char c, c2;
/*
* A bracket expression starting with an unquoted circumflex
* character produces unspecified results (IEEE 1003.2-1992,
* 3.13.2). This implementation treats it like '!', for
* consistency with the regular expression syntax.
* J.T. Conklin (conklin@ngai.kaleida.com)
*/
if (negate = (*pattern == '!' || *pattern == '^'))
++pattern;
for (ok = 0; (c = *pattern++) != ']';) {
if (c == '\\' && !(flags & FNM_NOESCAPE))
c = *pattern++;
if (c == EOS)
return (NULL);
if (*pattern == '-'
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
pattern += 2;
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
c2 = *pattern++;
if (c2 == EOS)
return (NULL);
if (c <= test && test <= c2)
ok = 1;
} else if (c == test)
ok = 1;
}
return (ok == negate ? NULL : pattern);
}
static void
_fnmatch_map (const char *opath, const char *orex, char **npath, char **nrex,
int flags) {
static char *path = NULL;
static char *rex = NULL;
char *p;
int i;
/*
* create copies of opath and orex; this depends on an
* ANSI implementation of realloc (accepts NULL pointer)
*/
path = realloc(path, strlen(opath) + 1);
rex = realloc(rex, strlen(orex) + 1);
if (path == NULL || rex == NULL) {
err (1, "fnmatch could not allocate internal buffer");
/*NOTREACHED*/
}
strcpy(path, opath);
strcpy(rex, orex);
/* fold case if necessary */
if (flags & FNM_CASEFOLD) {
for (p = path; *p != '\0'; p++) {
if (isupper(*p)) {
*p = _tolower(*p);
}
}
for (p = rex; *p != '\0'; p++) {
if (isupper(*p)) {
*p = _tolower(*p);
}
}
}
/*
* If either pattern or string contain _both_ a ':' and a '/',
* then we leave them exactly as they are. Otherwise, all colons
* are mapped to '/'.
*/
if (!((strchr(path, ':') && strchr(path, '/')) ||
(strchr(rex, ':') && strchr(rex, '/')))) {
for (i=0; i<2; i++) {
switch (i) {
case 0:
p = path;
break;
case 1:
p = rex;
break;
}
while (*p) {
if (*p == ':') {
*p = '/';
}
p++;
}
}
}
/* give the caller pointers to our buffer */
*npath = path;
*nrex = rex;
return;
}

1018
lib/libc/gen/fts.c Normal file

File diff suppressed because it is too large Load Diff

114
lib/libc/gen/getcwd.c Normal file
View File

@ -0,0 +1,114 @@
#line 1 ":trenco4:gno.src:lib:libc:gen:getcwd.c"
/*
* getwd originally by Derek Taubert. First appeared in GNO v1.0 (?).
* Modified for BSD 4.4 compatibility and dynamically allocated structs
* by Devin Reade.
*
* $Id: getcwd.c,v 1.1 1997/02/28 05:12:44 gdr Exp $
*
* This file is formatted for tabs every 8 columns.
*/
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#include <sys/param.h>
#include <sys/types.h>
#include <types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <orca.h>
#include <gno/gno.h>
#include <gsos.h>
char *
getcwd(char *pathname, size_t size) {
PrefixRecGS *prefx;
ResultBufPtr where;
int e, allocated, i;
char *result;
if (size == 0 && pathname != NULL) {
errno = EINVAL;
return NULL;
}
if ((prefx = malloc (sizeof(PrefixRecGS))) == NULL) {
return NULL;
}
if (pathname == NULL) {
size = MAXPATHLEN;
if ((pathname = malloc(size)) == NULL) {
e = errno;
free(prefx);
errno = e;
return NULL;
}
allocated = 1;
} else {
allocated = 0;
}
result = pathname;
if ((where = GOinit (size, NULL)) == NULL) {
e = errno;
free(prefx);
if (allocated) free(pathname);
errno = e;
return NULL;
}
prefx->pCount = 2;
prefx->buffer.getPrefix = (ResultBuf255Ptr) where;
for (i=0; i<2; i++) {
switch (i) {
case 0:
prefx->prefixNum = 0;
break;
case 1:
prefx->prefixNum = 8;
break;
}
GetPrefixGS(prefx);
if (i == 0 && _toolErr == 0 && where->bufString.length == 0) {
/* prefix 0 not set */
continue;
} else if ((e = _toolErr) != 0) {
e = (e == buffTooSmall) ? ERANGE : _mapErr(e);
result = NULL;
break;
} else {
e = errno;
strncpy(pathname, where->bufString.text, where->bufString.length);
pathname[where->bufString.length] = 0;
if (pathname[where->bufString.length-1] == ':') {
pathname[where->bufString.length-1] = '\0';
}
/* convert the filename? */
if (_mapPath(pathname) == NULL) {
e = EINVAL;
result = NULL;
}
break;
}
/* NOTREACHED */
}
free(prefx);
GOfree(where);
if (allocated && result == NULL) {
free(pathname);
}
errno = e;
return result;
}
char *
getwd (char *pathname) {
return getcwd(pathname, MAXPATHLEN);
}

451
lib/libc/gen/getgrent.c Normal file
View File

@ -0,0 +1,451 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This file is formatted with tab stops every 8 columns.
*
* $Id: getgrent.c,v 1.1 1997/02/28 05:12:44 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <paths.h>
#include <grp.h>
static FILE *_gr_fp;
static struct group _gr_group;
static int _gr_stayopen;
static int grscan(register int search, register int gid,
register const char *name);
static int start_gr(void);
#ifdef YP
#include <rpc/rpc.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
static int _gr_stepping_yp;
static int _gr_yp_enabled;
static int _getypgroup(struct group *, const char *, char *);
static int _nextypgroup(struct group *);
#endif
#define MAXGRP 200
static char *members[MAXGRP];
#define MAXLINELENGTH 1024
static char line[MAXLINELENGTH];
struct group *
getgrent(void)
{
if (!_gr_fp && !start_gr()) {
return NULL;
}
#ifdef YP
if (_gr_stepping_yp) {
if (_nextypgroup(&_gr_group))
return(&_gr_group);
}
tryagain:
#endif
if (!grscan(0, 0, NULL))
return(NULL);
#ifdef YP
if(_gr_group.gr_name[0] == '+' && _gr_group.gr_name[1]) {
_getypgroup(&_gr_group, &_gr_group.gr_name[1],
"group.byname");
} else if(_gr_group.gr_name[0] == '+') {
if (!_nextypgroup(&_gr_group))
goto tryagain;
else
return(&_gr_group);
}
#endif
return(&_gr_group);
}
struct group *
getgrnam(const char *name)
{
int rval;
if (!start_gr())
return(NULL);
#ifdef YP
tryagain:
#endif
rval = grscan(1, 0, name);
#ifdef YP
if(rval == -1 && (_gr_yp_enabled < 0 || (_gr_yp_enabled &&
_gr_group.gr_name[0] == '+'))) {
if (!(rval = _getypgroup(&_gr_group, name, "group.byname")))
goto tryagain;
}
#endif
if (!_gr_stayopen)
endgrent();
return(rval ? &_gr_group : NULL);
}
struct group *
#ifdef __STDC__
getgrgid(gid_t gid)
#else
getgrgid(gid)
gid_t gid;
#endif
{
int rval;
if (!start_gr())
return(NULL);
#ifdef YP
tryagain:
#endif
rval = grscan(1, gid, NULL);
#ifdef YP
if(rval == -1 && _gr_yp_enabled) {
char buf[16];
snprintf(buf, sizeof buf, "%d", (unsigned)gid);
if (!(rval = _getypgroup(&_gr_group, buf, "group.bygid")))
goto tryagain;
}
#endif
if (!_gr_stayopen)
endgrent();
return(rval ? &_gr_group : NULL);
}
static int
start_gr(void)
{
if (_gr_fp) {
rewind(_gr_fp);
return(1);
}
_gr_fp = fopen(_PATH_GROUP, "r");
if(!_gr_fp) return 0;
#ifdef YP
/*
* This is a disgusting hack, used to determine when YP is enabled.
* This would be easier if we had a group database to go along with
* the password database.
*/
{
char *line;
size_t linelen;
_gr_yp_enabled = 0;
while((line = fgetln(_gr_fp, &linelen)) != NULL) {
if(line[0] == '+') {
if(line[1] && !_gr_yp_enabled) {
_gr_yp_enabled = 1;
} else {
_gr_yp_enabled = -1;
break;
}
}
}
rewind(_gr_fp);
}
#endif
return 1;
}
int
setgrent(void)
{
return(setgroupent(0));
}
int
setgroupent(int stayopen)
{
if (!start_gr())
return(0);
_gr_stayopen = stayopen;
#ifdef YP
_gr_stepping_yp = 0;
#endif
return(1);
}
void
endgrent(void)
{
#ifdef YP
_gr_stepping_yp = 0;
#endif
if (_gr_fp) {
(void)fclose(_gr_fp);
_gr_fp = NULL;
}
}
static int
grscan(register int search, register int gid, register const char *name)
{
register char *cp, **m;
char *bp;
#ifdef YP
int _ypfound = 0;
#endif
for (;;) {
if (!fgets(line, sizeof(line), _gr_fp))
return(0);
bp = line;
/* skip lines that are too big */
if (!index(line, '\n')) {
int ch;
while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
;
continue;
}
if ((_gr_group.gr_name = strsep(&bp, ":\n")) == NULL)
break;
#ifdef YP
/*
* XXX We need to be careful to avoid proceeding
* past this point under certain circumstances or
* we risk dereferencing null pointers down below.
*/
if (_gr_group.gr_name[0] == '+') {
if (strlen(_gr_group.gr_name) == 1) {
switch(search) {
case 0:
return(1);
case 1:
return(-1);
default:
return(0);
}
} else {
if (!_getypgroup(&_gr_group, &_gr_group.gr_name[1],
"group.byname"))
continue;
/* We're going to override -- tell the world. */
members[0] = NULL;
_ypfound++;
}
}
#else
if (_gr_group.gr_name[0] == '+')
continue;
#endif /* YP */
if (search && name) {
if(strcmp(_gr_group.gr_name, name)) {
continue;
}
}
if ((_gr_group.gr_passwd = strsep(&bp, ":\n")) == NULL)
break;;
if (!(cp = strsep(&bp, ":\n")))
continue;
#ifdef YP
if (!_ypfound)
#endif
_gr_group.gr_gid = atoi(cp);
if (search && name == NULL && _gr_group.gr_gid != gid)
continue;
cp = NULL;
for (m = _gr_group.gr_mem = members;; bp++) {
if (m == &members[MAXGRP - 1])
break;
if (*bp == ',') {
if (cp) {
*bp = '\0';
*m++ = cp;
cp = NULL;
}
} else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
if (cp) {
*bp = '\0';
*m++ = cp;
}
break;
} else if (cp == NULL)
cp = bp;
}
*m = NULL;
return(1);
}
/* NOTREACHED */
return (0);
}
#ifdef YP
static int
_gr_breakout_yp(struct group *gr, char *result)
{
char *s, *cp;
char **m;
/*
* XXX If 's' ends up being a NULL pointer, punt on this group.
* It means the NIS group entry is badly formatted and should
* be skipped.
*/
if ((s = strsep(&result, ":")) == NULL) return 0; /* name */
gr->gr_name = s;
if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
gr->gr_passwd = s;
if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */
gr->gr_gid = atoi(s);
if ((s = result) == NULL) return 0;
cp = 0;
for (m = _gr_group.gr_mem = members; /**/; s++) {
if (m == &members[MAXGRP - 1]) {
break;
}
if (*s == ',') {
if (cp) {
*s = '\0';
*m++ = cp;
cp = NULL;
}
} else if (*s == '\0' || *s == '\n' || *s == ' ') {
if (cp) {
*s = '\0';
*m++ = cp;
}
break;
} else if (cp == NULL) {
cp = s;
}
}
*m = NULL;
return 1;
}
static char *_gr_yp_domain;
static int
_getypgroup(struct group *gr, const char *name, char *map)
{
char *result, *s;
static char resultbuf[1024];
int resultlen;
if(!_gr_yp_domain) {
if(yp_get_default_domain(&_gr_yp_domain))
return 0;
}
if(yp_match(_gr_yp_domain, map, name, strlen(name),
&result, &resultlen))
return 0;
s = strchr(result, '\n');
if(s) *s = '\0';
if(resultlen >= sizeof resultbuf) return 0;
strcpy(resultbuf, result);
result = resultbuf;
return(_gr_breakout_yp(gr, resultbuf));
}
static int
_nextypgroup(struct group *gr)
{
static char *key;
static int keylen;
char *lastkey, *result;
static char resultbuf[1024];
int resultlen;
int rv;
if(!_gr_yp_domain) {
if(yp_get_default_domain(&_gr_yp_domain))
return 0;
}
if(!_gr_stepping_yp) {
if(key) free(key);
rv = yp_first(_gr_yp_domain, "group.byname",
&key, &keylen, &result, &resultlen);
if(rv) {
return 0;
}
_gr_stepping_yp = 1;
goto unpack;
} else {
tryagain:
lastkey = key;
rv = yp_next(_gr_yp_domain, "group.byname", key, keylen,
&key, &keylen, &result, &resultlen);
free(lastkey);
unpack:
if(rv) {
_gr_stepping_yp = 0;
return 0;
}
if(resultlen > sizeof(resultbuf)) {
free(result);
goto tryagain;
}
strcpy(resultbuf, result);
free(result);
if((result = strchr(resultbuf, '\n')) != NULL)
*result = '\0';
if (_gr_breakout_yp(gr, resultbuf))
return(1);
else
goto tryagain;
}
}
#endif /* YP */

117
lib/libc/gen/getpass.c Normal file
View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* GDR: This file could probably be cleaned up a bit ...
*
* $Id: getpass.c,v 1.1 1997/02/28 05:12:44 gdr Exp $
*
* This file is formatted for tab stops every 8 characters.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getpass.c 5.9 (Berkeley) 5/6/91";
#endif /* LIBC_SCCS and not lint */
#include <sgtty.h>
#include <sys/signal.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stddef.h>
#include <texttool.h>
#include <sys/fcntl.h>
#include <signal.h>
#undef echo
char *
getpass(const char *prompt) {
struct sgttyb term;
register int ch;
register char *p;
FILE *fp, *outfp;
long omask;
int echo;
static char buf[_PASSWORD_LEN + 1];
/*
* read and write to /dev/tty if possible; else read from
* stdin and write to stderr.
*/
/* if ((outfp = fp = fopen(".tty", "w+")) == NULL) { */
if ((outfp = fp = fopen(".tty", "r+")) == NULL) {
outfp = stderr;
fp = stdin;
}
setbuf(outfp,NULL);
/*
* note - blocking signals isn't necessarily the
* right thing, but we leave it for now.
*/
omask = sigblock(sigmask(SIGINT)|sigmask(SIGTSTP));
/*(void)tcgetattr(fileno(fp), &term); */
gtty(fileno(fp),&term);
if (echo = (term.sg_flags & ECHO)) {
term.sg_flags &= ~ECHO;
stty(fileno(fp),&term);
/*(void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);*/
}
/* (void)fputs(prompt, outfp);*/
/* rewind(outfp); */ /* implied flush */
write(fileno(outfp),prompt,strlen(prompt));
/* for (p = buf; (ch = getc(fp)) != EOF && ch != '\n';) */
for (p = buf; (ch = ReadChar(0)&0x7F) != 0 && ch != '\n' && ch != '\r';)
if (p < buf + _PASSWORD_LEN)
*p++ = ch;
*p = '\0';
(void)write(fileno(outfp), "\r", 1);
if (echo) {
term.sg_flags |= ECHO;
stty(fileno(fp), &term);
}
(void)sigsetmask(omask);
if (fp != stdin)
(void)fclose(fp);
return(buf);
}

239
lib/libc/gen/getpwent.c Normal file
View File

@ -0,0 +1,239 @@
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This is an old implementation and needs to be replaced; just not quite
* yet -- gdr
*
* $Id: getpwent.c,v 1.1 1997/02/28 05:12:44 gdr Exp $
*
* This file is formatted with tab stops every 8 characters.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#define _PATH_PASSWD "/etc/passwd"
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getpwent.c 5.21 (Berkeley) 3/14/91";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#define LENGTH 128
#define _PATH_PASSWD "/etc/passwd"
static struct passwd _pw_passwd; /* password structure */
static char pwline[LENGTH]; /* line in /etc/passwd */
static FILE * f_passwd = NULL;
#if 0
static int _pw_stayopen = 0; /* keep fd's open */
#endif
static FILE *
_getpwfp (void) {
if (f_passwd == NULL) {
f_passwd = fopen(_PATH_PASSWD, "r");
if (f_passwd == NULL) {
/* this should really be going out via syslog */
errx(1, "couldn't open %s", _PATH_PASSWD);
}
}
return f_passwd;
}
static struct passwd *
_parsepw (struct passwd *_pw, char *line)
{
char *q, *r;
_pw->pw_fields = 0L; /* no fields filled in yet */
if ((q = strchr(line, '\n')) != NULL) {
*q = '\0';
}
/* user name */
_pw->pw_name = line;
if ((q = strchr(line,':')) == NULL) {
return NULL;
}
*q++ = '\0';
_pw->pw_fields |= _PWF_NAME;
/* password */
_pw->pw_passwd = q;
if ((q = strchr(q,':')) == NULL) {
return NULL;
}
*q++ = '\0';
_pw->pw_fields |= _PWF_PASSWD;
/* user id */
errno = 0;
_pw->pw_uid = (int) strtol(q, &r, 10);
if (errno == ERANGE || q == r) {
return NULL;
}
q = r;
*q++ = '\0';
_pw->pw_fields |= _PWF_UID;
/* group id */
errno = 0;
_pw->pw_gid = (int) strtol(q, &r, 10);
if (errno == ERANGE || q == r) {
return NULL;
}
q = r;
*q++ = '\0';
_pw->pw_fields |= _PWF_GID;
/* real name */
_pw->pw_gecos = q;
if ((q = strchr(q,':')) == NULL) {
return NULL;
}
*q++ = '\0';
_pw->pw_fields |= _PWF_GECOS;
/* home directory */
_pw->pw_dir = q;
if ((q = strchr(q,':')) == NULL) {
return NULL;
}
*q++ = '\0';
_pw->pw_fields |= _PWF_DIR;
/* shell -- last one, so handle it differently */
_pw->pw_shell = q;
if ((q = strchr(q,':')) != NULL) {
*q = '\0';
}
_pw->pw_fields |= _PWF_SHELL;
/* "not filled in":
* password change time
* user access class
* account expiry time
*/
_pw->pw_change = _pw->pw_expire = 0L;
_pw->pw_class = NULL;
return _pw;
}
struct passwd *
getpwent(void)
{
FILE *fp;
fp = _getpwfp();
if (fgets(pwline, LENGTH, fp) == NULL) {
return NULL;
}
return _parsepw (&_pw_passwd, pwline);
}
struct passwd *
getpwnam(char *name) {
FILE *fp;
struct passwd *result;
fp = _getpwfp();
rewind(fp);
while (fgets(pwline, LENGTH, fp) != NULL) {
result = _parsepw (&_pw_passwd, pwline);
if (result == NULL || !strcmp(name, result->pw_name)) {
return result;
}
}
return NULL;
}
struct passwd *
getpwuid(uid_t uid)
{
FILE *fp;
struct passwd *result;
fp = _getpwfp();
rewind(fp);
while (fgets(pwline, LENGTH, fp) != NULL) {
result = _parsepw (&_pw_passwd, pwline);
if (result == NULL || uid == result->pw_uid) {
return result;
}
}
return NULL;
}
int
setpwent(void)
{
if (f_passwd != NULL) {
rewind(f_passwd);
}
return 1;
}
void
endpwent(void)
{
if (f_passwd != NULL) {
fclose(f_passwd);
f_passwd = NULL;
}
}
#ifdef NOTDEFINED
int
setpassent(stayopen)
int stayopen;
{
_pw_keynum = 0;
_pw_stayopen = stayopen;
return(1);
}
#endif

205
lib/libc/gen/getttyent.c Normal file
View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getttyent.c 5.10 (Berkeley) 3/23/91";
#endif /* LIBC_SCCS and not lint */
#define index strchr
#include <ttyent.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
static char zapchar;
static FILE *tf;
static char *skip(register char *p);
static char *value(register char *p);
struct ttyent *
getttynam (const char *tty) {
register struct ttyent *t;
setttyent();
while (t = getttyent())
if (!strcmp(tty, t->ty_name))
break;
endttyent();
return (t);
}
struct ttyent *
getttyent(void) {
static struct ttyent tty;
register int c;
register char *p;
#define MAXLINELENGTH 100
static char line[MAXLINELENGTH];
if (!tf && !setttyent())
return (NULL);
for (;;) {
if (!fgets(p = line, sizeof(line), tf))
return (NULL);
/* skip lines that are too big */
if (!index(p, '\n')) {
while ((c = getc(tf)) != '\n' && c != EOF)
;
continue;
}
while (isspace(*p))
++p;
if (*p && *p != '#')
break;
}
zapchar = 0;
tty.ty_name = p;
p = skip(p);
if (!*(tty.ty_getty = p))
tty.ty_getty = tty.ty_type = NULL;
else {
p = skip(p);
if (!*(tty.ty_type = p))
tty.ty_type = NULL;
else
p = skip(p);
}
tty.ty_status = 0;
tty.ty_window = NULL;
#ifdef __ORCAC__
#define scmp(e) !strncmp(p, e, strlen(e) ) && isspace(p[strlen(e)])
#define vcmp(e) !strncmp(p, e, strlen(e) ) && p[strlen(e)] == '='
#else
#define scmp(e) !strncmp(p, e, sizeof e - 1) && isspace(p[sizeof e])
#define vcmp(e) !strncmp(p, e, sizeof e - 1) && p[sizeof e] == '='
#endif
for (; *p; p = skip(p)) {
if (scmp(_TTYS_OFF))
tty.ty_status &= ~TTY_ON;
else if (scmp(_TTYS_ON))
tty.ty_status |= TTY_ON;
else if (scmp(_TTYS_SECURE))
tty.ty_status |= TTY_SECURE;
else if (vcmp(_TTYS_WINDOW))
tty.ty_window = value(p);
else
break;
}
if (zapchar == '#' || *p == '#')
while ((c = *++p) == ' ' || c == '\t')
;
tty.ty_comment = p;
if (*p == 0)
tty.ty_comment = 0;
if (p = index(p, '\r'))
*p = '\0';
return (&tty);
}
#define QUOTED 1
/*
* Skip over the current field, removing quotes, and return a pointer to
* the next field.
*/
static char *
skip(register char *p)
{
register char *t;
register int c, q;
for (q = 0, t = p; (c = *p) != '\0'; p++) {
if (c == '"') {
q ^= QUOTED; /* obscure, but nice */
continue;
}
if (q == QUOTED && *p == '\\' && *(p+1) == '"')
p++;
*t++ = *p;
if (q == QUOTED)
continue;
if (c == '#') {
zapchar = c;
*p = 0;
break;
}
if (c == '\t' || c == ' ' || c == '\n' || c == '\r') {
zapchar = c;
*p++ = 0;
while ((c = *p) == '\t' || c == ' ' || c == '\n' || c == '\r')
p++;
break;
}
}
*--t = '\0';
return (p);
}
static char *
value(register char *p)
{
return ((p = index(p, '=')) ? ++p : NULL);
}
int
setttyent(void)
{
if (tf) {
(void)rewind(tf);
return (1);
} else if (tf = fopen(_PATH_TTYS, "r"))
return (1);
return (0);
}
int
endttyent(void)
{
int rval;
if (tf) {
rval = !(fclose(tf) == EOF);
tf = NULL;
return (rval);
}
return (1);
}

83
lib/libc/gen/hostname.c Normal file
View File

@ -0,0 +1,83 @@
/*
* $Id: hostname.c,v 1.1 1997/02/28 05:12:44 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <sys/param.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <orca.h>
#include <locator.h>
#include <memory.h>
#include <misctool.h>
typedef struct NMRec {
word blockLen;
unsigned char nameLength;
char nameString[64];
} NMRec;
typedef union {
struct {
word messageID;
word createFlag;
} w;
unsigned long l;
} ResponseR;
int
sethostname(const char *name, int namelen) {
int size;
NMRec rec;
ResponseR mbnResp;
strcpy(rec.nameString, "Procyon~GNO/ME~HoStNaMe");
rec.nameLength = 23;
size = MIN(MAXHOSTNAMELEN-1, namelen);
strncpy(rec.nameString+23, name, size);
(rec.nameString+23)[size] = 0;
rec.blockLen = 2 + (1+23) + (1+size);
mbnResp.l = MessageByName(1,(Pointer)&rec);
if (_toolErr) {
errno = ENOMEM;
return -1;
}
return 0;
}
int
gethostname(char *name, int namelen) {
NMRec rec = {30,23,"Procyon~GNO/ME~HoStNaMe"}; /* why blockLen = 30? */
ResponseR mbnResp;
Handle message;
mbnResp.l = MessageByName(0,(Pointer)&rec);
if (_toolErr) {
errno = ENOENT;
return -1;
}
#if 0
printf("MBN returned %X %X\n", mbnResp.w.messageID,
mbnResp.w.createFlag);
#endif
MessageCenter(getMessage,mbnResp.w.messageID,
message = NewHandle(0l,userid(),0,0l));
if (_toolErr) {
errno = ENOMEM;
return -1;
}
strncpy(name, (char *)*message+6+2+(1+23),
MIN(MAXHOSTNAMELEN, namelen));
DisposeHandle(message);
return 0;
}

68
lib/libc/gen/oldlog.c Normal file
View File

@ -0,0 +1,68 @@
/*
* old_syslog library routine. Used if syslogd is not present. This routine
* has a subset of the functions of syslogd. It always outputs to
* /etc/syslog, and it accepts only one string, and does no error checking.
* It also prints the facility/log level as a number.
*
* If you're sure syslogd will be available when your program is run (or you
* want syslog() to do nothing if it isn't), create a dummy old_syslog() that
* simply returns. This will make your program smaller.
*
* Phillip Vandry, August 1993.
*
* $Id: oldlog.c,v 1.1 1997/02/28 05:12:44 gdr Exp $
*
* This file is formatted with tab stops every 8 columns.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <stdio.h>
#include <fcntl.h>
#include <memory.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/syslog.h>
#define _PATH_SYSLOG "/etc/syslog"
/* Perhaps this struct decl belongs in <sys/syslog.h> ? */
struct syslogd {
int version; /* == 0 */
int prio; /* priority and facility */
int numstrings; /* number of strings sent to syslogd */
int string1; /* offset of string #1 */
/* offset of more strings. This routine handles only one string */
int string1_len; /* length of string #1 (GS/OS string) */
char string1_text; /* variable length */
};
void
old_syslog (Handle datahand)
{
struct syslogd *data;
static time_t trec;
int where;
static char number[32];
HLock(datahand);
data = (struct syslogd *)*datahand;
if ((where = open(_PATH_SYSLOG, O_APPEND|O_WRONLY|O_CREAT)) == -1) {
return;
}
trec = time(NULL);
sprintf(number,"%s: <%d> ", ctime(&trec), data->prio);
write(where,number,(size_t)strlen(number));
write(where,&(data->string1_text),(size_t)data->string1_len);
write(where,"\r",1l);
close(where);
DisposeHandle(datahand);
}

201
lib/libc/gen/popen.c Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software written by Ken Arnold and
* published in UNIX Review, Vol. 6, No. 8.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char *sccsid = "from: @(#)popen.c 5.15 (Berkeley) 2/23/91";
static char *rcsid = "popen.c,v 1.5 1993/08/26 00:44:55 jtc Exp";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <paths.h>
#include <assert.h>
static pid_t *pids;
#ifdef __GNO__
#pragma databank 1
static void
_popen_child(int *pdes, char type, char *command)
{
if (type == 'r') {
if (pdes[1] != STDOUT_FILENO) {
(void) dup2(pdes[1], STDOUT_FILENO);
(void) close(pdes[1]);
}
(void) close(pdes[0]);
} else {
if (pdes[0] != STDIN_FILENO) {
(void) dup2(pdes[0], STDIN_FILENO);
(void) close(pdes[0]);
}
(void) close(pdes[1]);
}
/* change this when we have an sh(1) for GNO */
#if 1
execl(_PATH_GSHELL, "gsh", "-c", command, (char *) 0);
#else
execl(_PATH_BSHELL, "sh", "-c", command, (char *) 0);
#endif
_exit(127);
}
#pragma databank 0
#endif /* __GNO__ */
FILE *
popen(const char *command, const char *type)
{
FILE *iop;
int fds, pid;
int pdes[2];
if (*type != 'r' && *type != 'w' || type[1]) {
errno = EINVAL;
return (NULL);
}
if (pids == NULL) {
if ((fds = getdtablesize()) <= 0) {
return (NULL);
}
if ((pids = malloc(fds * sizeof(int))) == NULL) {
return NULL;
}
bzero((char *) pids, fds * sizeof(pid_t));
}
if (pipe(pdes) < 0) {
return (NULL);
}
#ifdef __GNO__
pid = fork2(_popen_child, 1024, 0, "forked child of popen", 5,
pdes, *type, command);
switch (pid) {
#else
switch (pid = vfork()) {
#endif
case -1: /* error */
(void) close(pdes[0]);
(void) close(pdes[1]);
return (NULL);
/* NOTREACHED */
#ifndef __GNO__
case 0: /* child */
if (*type == 'r') {
if (pdes[1] != STDOUT_FILENO) {
(void) dup2(pdes[1], STDOUT_FILENO);
(void) close(pdes[1]);
}
(void) close(pdes[0]);
} else {
if (pdes[0] != STDIN_FILENO) {
(void) dup2(pdes[0], STDIN_FILENO);
(void) close(pdes[0]);
}
(void) close(pdes[1]);
}
execl(_PATH_BSHELL, "sh", "-c", command, (char *) 0);
_exit(127);
/* NOTREACHED */
#endif /* ! __GNO__ */
}
/* parent; assume fdopen can't fail... */
if (*type == 'r') {
iop = fdopen(pdes[0], type);
(void) close(pdes[1]);
} else {
iop = fdopen(pdes[1], type);
(void) close(pdes[0]);
}
/*
* this assert may be removed when getdtablesize is replaced by
* a kernel system call rather than just a stub returning OPEN_MAX
*/
assert(fileno(iop) < getdtablesize());
pids[fileno(iop)] = pid;
return (iop);
}
int
pclose(FILE * iop)
{
register int fdes;
int omask;
union wait pstat;
pid_t pid;
/*
* this assert may be removed when getdtablesize is replaced by
* a kernel system call rather than just a stub returning OPEN_MAX
*/
assert(fileno(iop) < getdtablesize());
/*
* pclose returns -1 if stream is not associated with a
* `popened' command, if already `pclosed', or waitpid
* returns an error.
*/
fdes = fileno(iop);
if (pids == NULL || pids[fdes] == 0) {
return (-1);
}
(void) fclose(iop);
do {
pid = waitpid(pids[fdes], &pstat, 0);
} while (pid == -1 && errno == EINTR);
pids[fdes] = 0;
return (pid == -1 ? -1 : pstat.w_retcode);
}

125
lib/libc/gen/pwcache.c Normal file
View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)pwcache.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <utmp.h>
#include <pwd.h>
#include <grp.h>
#define NCACHE 64 /* power of 2 */
#define MASK (NCACHE - 1) /* bits to store with */
char *group_from_gid(gid_t gid, int nogroup);
char *user_from_uid(uid_t uid, int nouser);
char *
user_from_uid(uid_t uid, int nouser)
{
static struct ncache {
uid_t uid;
int found;
char name[UT_NAMESIZE + 1];
} c_uid[NCACHE];
static int pwopen;
register struct passwd *pw;
register struct ncache *cp;
cp = c_uid + (uid & MASK);
if (cp->uid != uid || !*cp->name) {
if (pwopen == 0) {
setpassent(1);
pwopen = 1;
}
pw = getpwuid(uid);
cp->uid = uid;
if (pw != NULL) {
cp->found = 1;
(void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
cp->name[UT_NAMESIZE] = '\0';
} else {
cp->found = 0;
(void)snprintf(cp->name, UT_NAMESIZE, "%u", uid);
if (nouser)
return (NULL);
}
}
return (cp->name);
}
char *
group_from_gid(gid_t gid, int nogroup)
{
static struct ncache {
gid_t gid;
int found;
char name[UT_NAMESIZE + 1];
} c_gid[NCACHE];
static int gropen;
struct group *gr;
struct ncache *cp;
cp = c_gid + (gid & MASK);
if (cp->gid != gid || !*cp->name) {
if (gropen == 0) {
setgroupent(1);
gropen = 1;
}
gr = getgrgid(gid);
cp->gid = gid;
if (gr != NULL) {
cp->found = 1;
(void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
cp->name[UT_NAMESIZE] = '\0';
} else {
cp->found = 0;
(void)snprintf(cp->name, UT_NAMESIZE, "%u", gid);
if (nogroup)
return (NULL);
}
}
return (cp->name);
}

157
lib/libc/gen/scandir.c Normal file
View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This file is formatted for tab stops set every 8 columns.
*
* $Id: scandir.c,v 1.1 1997/02/28 05:12:45 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
#endif /* LIBC_SCCS and not lint */
/*
* Scan the directory dirname calling select to make a list of selected
* directory entries then sort using qsort and compare routine dcomp.
* Returns the number of entries and a pointer to a list of pointers to
* struct dirent (through namelist). Returns -1 if there were any errors.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/*
* The DIRSIZ macro is the minimum record length which will hold the directory
* entry. This requires the amount of space in struct dirent without the
* d_name field, plus enough space for the name and a terminating nul byte
* (dp->d_namlen + 1), rounded up to a 4 byte boundary.
*/
#undef DIRSIZ
#define DIRSIZ(dp) \
((sizeof(struct dirent) - sizeof(dp)->d_name) + \
(((dp)->d_namlen + 1 + 3) &~ 3))
/*
* This is the quantum by which we allocate slots for of directory
* entries. Using 64 * sizeof(caddr_t) gives as 256 bytes at a time.
*/
#define QUANTUM 64
int
scandir(const char *dirname,
struct dirent ***namelist,
int (*select) (struct dirent *),
int (*dcomp) (const void *, const void *))
{
register struct dirent *d, *p, **names;
register size_t nitems;
long arraysz;
DIR *dirp;
if ((dirp = opendir(dirname)) == NULL)
return(-1);
arraysz = QUANTUM;
if ((names = malloc (arraysz * sizeof(struct dirent *))) == NULL) {
closedir(dirp);
errno = ENOMEM;
return -1;
}
nitems = 0;
while ((d = readdir(dirp)) != NULL) {
if (select != NULL && !(*select)(d))
continue; /* just selected names */
/*
* Make a minimum size copy of the data
*/
p = (struct dirent *)malloc(DIRSIZ(d));
if (p == NULL)
return(-1);
p->d_fileno = d->d_fileno;
p->d_type = d->d_type;
p->d_reclen = d->d_reclen;
p->d_namlen = d->d_namlen;
bcopy(d->d_name, p->d_name, p->d_namlen + 1);
/*
* Check to make sure the array has space left and
* realloc the maximum size.
*/
if (++nitems >= arraysz) {
arraysz += QUANTUM;
names = realloc(names,
arraysz * sizeof(struct dirent *));
if (names == NULL) {
closedir(dirp);
errno = ENOMEM;
return -1;
}
}
names[nitems-1] = p;
}
closedir(dirp);
if (nitems && dcomp != NULL)
qsort(names, nitems, sizeof(struct dirent *), dcomp);
*namelist = names;
return(nitems);
}
/*
* Alphabetic order comparison routine for those who want it.
*/
int
alphasort(const void *d1, const void *d2)
{
return(strcmp((*(struct dirent **)d1)->d_name,
(*(struct dirent **)d2)->d_name));
}
int
alphacasesort(const void *d1, const void *d2)
{
return(strcasecmp((*(struct dirent **)d1)->d_name,
(*(struct dirent **)d2)->d_name));
}

177
lib/libc/gen/setjmp.asm Normal file
View File

@ -0,0 +1,177 @@
*
* Modified ORCA/C setjmp() and longjmp() routines to save and restore sigmask
*
* Original code from orcalib 2.0.1 - Copyright Byte Works, Inc.
* changes by Derek Taubert
* June 14, 1995
*
* $Id: setjmp.asm,v 1.1 1997/02/28 05:12:45 gdr Exp $
*
case on
dummy start ; ends up in .root
end
LONGA ON
LONGI ON
setjmp START
TSC
PHD
TCD
CLC
ADC #$0004
STA [$04] ; stack pointer
LDY #$0002
LDA $01,S
STA [$04],Y ; direct page register
LDY #$0004
LDA $00
STA [$04],Y ; LSB program counter
INY
INY
LDA $02
STA [$04],Y ; MSB program counter
; start sigmask changes
pea $0000
pea $0000
jsl sigblock
ldy #$0008
sta [$04],Y ; LSB sigmask
iny
iny
txa
sta [$04],Y ; MSB sigmask
; end sigmask changes
PLD
PHB
PLX
PLY
PLA
PLA
PHY
PHX
PLB
LDA #$0000
RTL
END
LONGA ON
LONGI ON
longjmp START
TSC
TCD
PHB
PHK
PLB
; start sigmask changes
ldy #$000A
lda [$04],Y ; MSB sigmask
pha
dey
dey
lda [$04],Y ; LSB sigmask
pha
jsl sigsetmask
LDY #$0006
lstk LDA [$04],Y
STA sp,Y
DEY
DEY
BPL lstk
LDX $08
BNE argok
INX
; end sigmask changes
argok PLB
LDA >sp
TCS
LDA >pc+$00000002
STA $02,S
LDA >pc
STA $00,S
LDA >dp
TCD
TXA
RTL
sp DC H'AD'
DC H'00'
dp DC H'00'
DC H'00'
pc DC H'19'
DC H'00'
DC H'00'
DC H'04'
END
LONGA ON
LONGI ON
_setjmp START
TSC
PHD
TCD
CLC
ADC #$0004
STA [$04]
LDY #$0002
LDA $01,S
STA [$04],Y
LDY #$0004
LDA $00
STA [$04],Y
INY
INY
LDA $02
STA [$04],Y
PLD
PHB
PLX
PLY
PLA
PLA
PHY
PHX
PLB
LDA #$0000
RTL
END
LONGA ON
LONGI ON
_longjmp START
TSC
TCD
PHB
PHK
PLB
LDX $08
BNE argok
INX
argok LDY #$0006
lstk LDA [$04],Y
STA sp,Y
DEY
DEY
BPL lstk
PLB
LDA >sp
TCS
LDA >pc+$00000002
STA $02,S
LDA >pc
STA $00,S
LDA >dp
TCD
TXA
RTL
sp DC H'AD'
DC H'00'
dp DC H'00'
DC H'00'
pc DC H'19'
DC H'00'
DC H'00'
DC H'04'
END

54
lib/libc/gen/sleep.c Normal file
View File

@ -0,0 +1,54 @@
/*
* The sleep(3) code is from BSD 4.3-reno, heavily modified (shorted)
* for use with GNO.
*
* $Id: sleep.c,v 1.1 1997/02/28 05:12:45 gdr Exp $
*
* This file has been formatted for tabs every 8 columns
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <signal.h>
#include <unistd.h>
static int _ringring;
#pragma databank 1
static void
_sleephandler(int sig, int code) {
_ringring = 1;
}
#pragma databank 0
unsigned int
sleep(unsigned int seconds) {
sig_t ovec;
long omask;
if (seconds == 0) {
return 0;
}
ovec = signal(SIGALRM, _sleephandler);
omask = sigblock(sigmask(SIGALRM));
_ringring = 0;
alarm(seconds);
while (!_ringring) {
sigpause(omask &~ sigmask(SIGALRM));
}
signal(SIGALRM, ovec);
sigsetmask(omask);
return 0;
}
int pause(void)
{
sigpause(0L);
return -1;
}

501
lib/libc/gen/syslog.asm Normal file
View File

@ -0,0 +1,501 @@
* These syslog() related routines use syslogd. They replace the old
* syslog() routines in the lbsd library.
*
* If syslogd is not found, syslog() calls old_syslog with the handle it
* would have passed to syslogd. If you are sure your program will have
* syslogd available when it is run, you can replace old_syslog() with
* a dummy routine that does nothing and returns. This will make your
* program smaller.
*
* syslogd is built into init and is automatically started by it. I
* recommend that you use init with GNO/ME 2.0
*
* Phillip Vandry, August 1993
*
* $Id: syslog.asm,v 1.1 1997/02/28 05:12:45 gdr Exp $
*
* This file is formatted for tab stops at positions 10, 16, 41, 40, 57,
* 65, and 73 (standard Orca/M systabs setting).
*
keep syslog
mcopy syslog.mac
case on
dummy start ; ends up in .root
end
syslog start libc_gen__
tsc
sec
sbc #$8
tcs
phd
tcd
* Direct: 1=va_list, 9=RTL, 12=prio, 14=char *, 18=args
lda #0
sta 3
sta 7
tdc
clc
adc #18
sta 1
sta 5
pea 0
tdc
inc a
pha
pei 16
pei 14
pei 12
jsl vsyslog
lda 1
clc
sec
sbc 5
tax ; num extra parms
* Direct: 1=va_list, 9=RTL, 12=prio, 14=char *, 18=args
lda 10
sta 16,x
lda 9
sta 15,x
pld
tsc
clc
adc #14
phx
adc 1,s
tcs
rtl
end
vsyslog start libc_gen__
using syslog_dat
space equ 26
argstart equ space+4
tsc
sec
sbc #space
tcs
phd
tcd
phb
prio equ argstart
format equ argstart+2
valist equ argstart+6
sendhand equ 1
sendptr equ 5
lerrno equ 9
errlen equ 9
chand equ 11
cptr equ 15
cumlen equ 19
error equ 23
lda >~USER_ID ; uck! bad name!
sta >memid
* Log only if bit clear in LogMask
lda >errno
sta lerrno
lda prio
and #7
tax
lda >LogMask
lsrloop lsr a
dex
bpl lsrloop
* carry = apropriate bit
bcc dolog
* get rif of parameters by running through sprintf
jsr mksendhand
pei valist+2
pei valist
pei format+2
pei format
pei sendptr+2
pei sendptr
jsl vsprintf
~DisposeHandle <sendhand
brl return
dolog anop
lda prio
and #$3f8
bne gotone
lda prio
ora >LogFacility
sta prio
gotone anop
jsr mksendhand
jsr cpsendhand
lda >LogTag
sta cptr
lda >LogTag+2
sta cptr+2
ora cptr
beq notag
lda >TagLen
bne already
ldy #0
short m
lppp lda [cptr],y
beq foundlen
iny
bra lppp
foundlen long m
tya
sta >TagLen
already sta [cumlen]
tay
short m
fincp2 dey
bmi fincp
lda [cptr],y
sta [sendptr],y
bra fincp2
fincp long m
lda [cumlen]
clc
adc sendptr
sta sendptr
lda sendptr+2
adc #0
sta sendptr+2
notag anop
lda >LogFlag
lsr a
bcc nopid
pha
ldx #$0903
jsl $e10008 ; getpid
pea fmt|-16
pea fmt
pei sendptr+2
pei sendptr
jsl sprintf
pha
clc
adc [cumlen]
sta [cumlen]
pla
clc
adc sendptr
sta sendptr
lda sendptr+2
adc #0
sta sendptr+2
nopid anop
lda >LogTag
ora >LogTag+2
beq notagsecond
lda [cumlen]
inc a
inc a
sta [cumlen]
lda #$203a
sta [sendptr]
lda sendptr
clc
adc #2
sta sendptr
lda sendptr+2
adc #0
sta sendptr+2
notagsecond anop
lda lerrno
bne isone
lda #ptrtozero
sta error
lda #^ptrtozero
sta error+2
bra none
isone pha
jsl strerror
sta error
stx error+2
phx
pha
jsl strlen
sta errlen
none ldx #2 ; = bytes needed in copy (one null+slop)
ldy #0
runthrough lda [format],y
cmp #$6d25 ; '%m'
beq account
and #$ff
beq endstring
iny
inx
bra runthrough
account iny
iny
txa
clc
adc errlen
tax
bra runthrough
endstring pha
pha
pea 0
phx ; length
stz chand
stz chand+2
lda format
sta cptr
lda format+2
sta cptr+2
lda >memid
pha
pea $4000
pha
pha
~NewHandle *,*,*,*
pla
plx
bcs impossible
sta chand
stx chand+2
ldy #2
lda [chand],y
sta cptr+2
lda [chand]
sta cptr
pea 0 ; offset in source
ldy #0 ; offset in dest
realtime tyx
ply
lda [format],y
cmp #$6d25 ; '%m'
beq coper
and #$ff
beq excited
iny
phy
txy
sta [cptr],y
iny
bra realtime
coper iny
iny
phy
txy ; Y=offset in destination
pea 0 ; offset in source
anotherreal tyx
ply
lda [error],y
and #$ff
beq donerr
iny
phy
txy
sta [cptr],y
iny
bra anotherreal
donerr txy
bra realtime
excited txy
sta [cptr],y ; zero
impossible anop ; jump here if malloc() failed
pei valist+2
pei valist
pei cptr+2
pei cptr
pei sendptr+2
pei sendptr
jsl vsprintf
clc
adc [cumlen]
sta [cumlen]
lda >LogFlag
and #$20 ; PERROR
beq noper
ldx cumlen
ldy cumlen+2
lda #3
jsl WriteGString ; echo on standard error
ldx #nlonly
ldy #^nlonly
lda #3
jsl WriteGString
noper lda chand
ora chand+2
beq nochand
~DisposeHandle <chand
nochand pei sendhand+2
pei sendhand
pea portname|-16
pea portname
jsl pgetport
cmp #$ffff
beq nosyslogd
pha
jsl psend
ldy #6
tryagain lda [sendhand],y
cmp >memid
bne return
cop $7f
bra tryagain
return plb
lda argstart-3
sta valist+1
lda argstart-2
sta valist+2
pld
tsc
clc
adc #(space+10)
tcs
rtl
nosyslogd jsl old_syslog
bra return
mksendhand pha
pha
pea 0
pea 1024
lda >memid
pha
pea $4000
pha
pha
~NewHandle *,*,*,*
plx
stx sendhand
plx
stx sendhand+2
bcs giveup
ldy #2
lda [sendhand],y
sta sendptr+2
lda [sendhand]
sta sendptr
rts
giveup pea 1
jsl sleep
bra mksendhand
cpsendhand ldy #(Xthis-Xsyslog-2) ; is even
phb
phk
plb
still lda Xsyslog,y
sta [sendptr],y
dey
dey
bpl still
plb
ldy #2
lda prio
sta [sendptr],y
lda sendptr
clc
adc #(Xthis-Xsyslog)
sta cumlen
lda sendptr+2
adc #0
sta cumlen+2
lda #0
sta [cumlen]
lda cumlen
clc
adc #2
sta sendptr
lda cumlen+2
adc #0
sta sendptr+2
rts
end
setlogmask start libc_gen__
using syslog_dat
* Stack: 1:RTL, 4:mask
lda 4,s
tax
lda >LogMask
sta 4,s
txa
sta >LogMask
phb
plx
ply
pla
phy
phx
plb
rtl
end
closelog start libc_gen__
using syslog_dat
rtl
end
openlog start libc_gen__
using syslog_dat
phb
plx
ply
* Stack: 1:char *, 5:int, 7:int
lda 1,s
ora 3,s
beq notag
pla
sta >LogTag
pla
sta >LogTag+2
lda #0
sta >TagLen
dc h'a9'
notag pla
pla
wastag pla
sta >LogFlag
pla
sta >LogFacility
phy
phx
plb
rtl
end
syslog_dat privdata libc_gen__
LogTag ds 4
TagLen ds 2
LogFlag ds 2
LogMask ds 2
LogFacility ds 2
memid ds 2
Xsyslog dc i'0,0,1,0,Xthis-Xsyslog'
Xthis anop
fmt dc c'[%u] ',h'0'
portname dc c'syslogd'
ptrtozero dc h'0'
nlonly dc h'01 00 0d'
end

146
lib/libc/gen/syslog.mac Normal file
View File

@ -0,0 +1,146 @@
macro
&lab ~DisposeHandle &p1
&lab ph4 &p1
ldx #$1002
jsl $E10000
mend
macro
&lab ~NewHandle &p1,&p2,&p3,&p4
&lab ph4 &p1
ph2 &p2
ph2 &p2
ph4 &p4
ldx #$0902
jsl $E10000
mend
macro
&l long &a,&b
lclb &i
lclb &m
&a amid &a,1,1
&m setb ("&a"="M").or.("&a"="m")
&i setb ("&a"="I").or.("&a"="i")
aif c:&b=0,.a
&b amid &b,1,1
&m setb ("&b"="M").or.("&b"="m").or.&m
&i setb ("&b"="I").or.("&b"="i").or.&i
.a
&l rep #&m*32+&i*16
aif .not.&m,.b
longa on
.b
aif .not.&i,.c
longi on
.c
mend
macro
&l ph2 &n1
aif "&n1"="*",.f
lclc &c
&l anop
&c amid &n1,1,1
aif "&c"="#",.d
aif s:longa=1,.a
rep #%00100000
.a
aif "&c"<>"{",.b
&c amid &n1,l:&n1,1
aif "&c"<>"}",.g
&n1 amid &n1,2,l:&n1-2
lda (&n1)
pha
ago .e
.b
aif "&c"="<",.c
lda &n1
pha
ago .e
.c
&n1 amid &n1,2,l:&n1-1
pei &n1
ago .e
.d
&n1 amid &n1,2,l:&n1-1
pea &n1
ago .f
.e
aif s:longa=1,.f
sep #%00100000
.f
mexit
.g
mnote "Missing closing '}'",16
mend
macro
&l ph4 &n1
aif "&n1"="*",.f
lclc &c
&l anop
&c amid &n1,1,1
aif "&c"="#",.d
aif s:longa=1,.a
rep #%00100000
.a
aif "&c"<>"{",.b
&c amid &n1,l:&n1,1
aif "&c"<>"}",.g
&n1 amid &n1,2,l:&n1-2
ldy #2
lda (&n1),y
pha
lda (&n1)
pha
ago .e
.b
aif "&c"<>"[",.c
ldy #2
lda &n1,y
pha
lda &n1
pha
ago .e
.c
aif "&c"<>"<",.c1
&n1 amid &n1,2,l:&n1-1
pei &n1+2
pei &n1
ago .e
.c1
lda &n1+2
pha
lda &n1
pha
ago .e
.d
&n1 amid &n1,2,l:&n1-1
pea +(&n1)|-16
pea &n1
ago .f
.e
aif s:longa=1,.f
sep #%00100000
.f
mexit
.g
mnote "Missing closing '}'",16
mend
macro
&l short &a,&b
lclb &i
lclb &m
&a amid &a,1,1
&m setb ("&a"="M").or.("&a"="m")
&i setb ("&a"="I").or.("&a"="i")
aif c:&b=0,.a
&b amid &b,1,1
&m setb ("&b"="M").or.("&b"="m").or.&m
&i setb ("&b"="I").or.("&b"="i").or.&i
.a
&l sep #&m*32+&i*16
aif .not.&m,.b
longa off
.b
aif .not.&i,.c
longi off
.c
mend

501
lib/libc/gen/syslog2.asm Normal file
View File

@ -0,0 +1,501 @@
* These syslog() related routines use syslogd. They replace the old
* syslog() routines in the lbsd library.
*
* If syslogd is not found, syslog() calls old_syslog with the handle it
* would have passed to syslogd. If you are sure your program will have
* syslogd available when it is run, you can replace old_syslog() with
* a dummy routine that does nothing and returns. This will make your
* program smaller.
*
* syslogd is built into init and is automatically started by it. I
* recommend that you use init with GNO/ME 2.0
*
* Phillip Vandry, August 1993
*
* $Id: syslog2.asm,v 1.1 1997/02/28 05:12:45 gdr Exp $
*
* This file is formatted for tab stops at positions 10, 16, 41, 40, 57,
* 65, and 73 (standard Orca/M systabs setting).
*
keep syslog
mcopy syslog.mac
case on
dummy start ; ends up in .root
end
syslog start libc_gen__
tsc
sec
sbc #$8
tcs
phd
tcd
* Direct: 1=va_list, 9=RTL, 12=prio, 14=char *, 18=args
lda #0
sta 3
sta 7
tdc
clc
adc #18
sta 1
sta 5
pea 0
tdc
inc a
pha
pei 16
pei 14
pei 12
jsl vsyslog
lda 1
clc
sec
sbc 5
tax ; num extra parms
* Direct: 1=va_list, 9=RTL, 12=prio, 14=char *, 18=args
lda 10
sta 16,x
lda 9
sta 15,x
pld
tsc
clc
adc #14
phx
adc 1,s
tcs
rtl
end
vsyslog start libc_gen__
using syslog_dat
space equ 26
argstart equ space+4
tsc
sec
sbc #space
tcs
phd
tcd
phb
prio equ argstart
format equ argstart+2
valist equ argstart+6
sendhand equ 1
sendptr equ 5
lerrno equ 9
errlen equ 9
chand equ 11
cptr equ 15
cumlen equ 19
error equ 23
lda >~USER_ID ; uck! bad name!
sta >memid
* Log only if bit clear in LogMask
lda >errno
sta lerrno
lda prio
and #7
tax
lda >LogMask
lsrloop lsr a
dex
bpl lsrloop
* carry = apropriate bit
bcc dolog
* get rif of parameters by running through sprintf
jsr mksendhand
pei valist+2
pei valist
pei format+2
pei format
pei sendptr+2
pei sendptr
jsl vsprintf
~DisposeHandle <sendhand
brl return
dolog anop
lda prio
and #$3f8
bne gotone
lda prio
ora >LogFacility
sta prio
gotone anop
jsr mksendhand
jsr cpsendhand
lda >LogTag
sta cptr
lda >LogTag+2
sta cptr+2
ora cptr
beq notag
lda >TagLen
bne already
ldy #0
short m
lppp lda [cptr],y
beq foundlen
iny
bra lppp
foundlen long m
tya
sta >TagLen
already sta [cumlen]
tay
short m
fincp2 dey
bmi fincp
lda [cptr],y
sta [sendptr],y
bra fincp2
fincp long m
lda [cumlen]
clc
adc sendptr
sta sendptr
lda sendptr+2
adc #0
sta sendptr+2
notag anop
lda >LogFlag
lsr a
bcc nopid
pha
ldx #$0903
jsl $e10008 ; getpid
pea fmt|-16
pea fmt
pei sendptr+2
pei sendptr
jsl sprintf
pha
clc
adc [cumlen]
sta [cumlen]
pla
clc
adc sendptr
sta sendptr
lda sendptr+2
adc #0
sta sendptr+2
nopid anop
lda >LogTag
ora >LogTag+2
beq notagsecond
lda [cumlen]
inc a
inc a
sta [cumlen]
lda #$203a
sta [sendptr]
lda sendptr
clc
adc #2
sta sendptr
lda sendptr+2
adc #0
sta sendptr+2
notagsecond anop
lda lerrno
bne isone
lda #ptrtozero
sta error
lda #^ptrtozero
sta error+2
bra none
isone pha
jsl strerror
sta error
stx error+2
phx
pha
jsl strlen
sta errlen
none ldx #2 ; = bytes needed in copy (one null+slop)
ldy #0
runthrough lda [format],y
cmp #$6d25 ; '%m'
beq account
and #$ff
beq endstring
iny
inx
bra runthrough
account iny
iny
txa
clc
adc errlen
tax
bra runthrough
endstring pha
pha
pea 0
phx ; length
stz chand
stz chand+2
lda format
sta cptr
lda format+2
sta cptr+2
lda >memid
pha
pea $4000
pha
pha
~NewHandle *,*,*,*
pla
plx
bcs impossible
sta chand
stx chand+2
ldy #2
lda [chand],y
sta cptr+2
lda [chand]
sta cptr
pea 0 ; offset in source
ldy #0 ; offset in dest
realtime tyx
ply
lda [format],y
cmp #$6d25 ; '%m'
beq coper
and #$ff
beq excited
iny
phy
txy
sta [cptr],y
iny
bra realtime
coper iny
iny
phy
txy ; Y=offset in destination
pea 0 ; offset in source
anotherreal tyx
ply
lda [error],y
and #$ff
beq donerr
iny
phy
txy
sta [cptr],y
iny
bra anotherreal
donerr txy
bra realtime
excited txy
sta [cptr],y ; zero
impossible anop ; jump here if malloc() failed
pei valist+2
pei valist
pei cptr+2
pei cptr
pei sendptr+2
pei sendptr
jsl vsprintf
clc
adc [cumlen]
sta [cumlen]
lda >LogFlag
and #$20 ; PERROR
beq noper
ldx cumlen
ldy cumlen+2
lda #3
jsl WriteGString ; echo on standard error
ldx #nlonly
ldy #^nlonly
lda #3
jsl WriteGString
noper lda chand
ora chand+2
beq nochand
~DisposeHandle <chand
nochand pei sendhand+2
pei sendhand
pea portname|-16
pea portname
jsl pgetport
cmp #$ffff
beq nosyslogd
pha
jsl psend
ldy #6
tryagain lda [sendhand],y
cmp >memid
bne return
cop $7f
bra tryagain
return plb
lda argstart-3
sta valist+1
lda argstart-2
sta valist+2
pld
tsc
clc
adc #(space+10)
tcs
rtl
nosyslogd jsl old_syslog
bra return
mksendhand pha
pha
pea 0
pea 1024
lda >memid
pha
pea $4000
pha
pha
~NewHandle *,*,*,*
plx
stx sendhand
plx
stx sendhand+2
bcs giveup
ldy #2
lda [sendhand],y
sta sendptr+2
lda [sendhand]
sta sendptr
rts
giveup pea 1
jsl sleep
bra mksendhand
cpsendhand ldy #(Xthis-Xsyslog-2) ; is even
phb
phk
plb
still lda Xsyslog,y
sta [sendptr],y
dey
dey
bpl still
plb
ldy #2
lda prio
sta [sendptr],y
lda sendptr
clc
adc #(Xthis-Xsyslog)
sta cumlen
lda sendptr+2
adc #0
sta cumlen+2
lda #0
sta [cumlen]
lda cumlen
clc
adc #2
sta sendptr
lda cumlen+2
adc #0
sta sendptr+2
rts
end
setlogmask start libc_gen__
using syslog_dat
* Stack: 1:RTL, 4:mask
lda 4,s
tax
lda >LogMask
sta 4,s
txa
sta >LogMask
phb
plx
ply
pla
phy
phx
plb
rtl
end
closelog start libc_gen__
using syslog_dat
rtl
end
openlog start libc_gen__
using syslog_dat
phb
plx
ply
* Stack: 1:char *, 5:int, 7:int
lda 1,s
ora 3,s
beq notag
pla
sta >LogTag
pla
sta >LogTag+2
lda #0
sta >TagLen
dc h'a9'
notag pla
pla
wastag pla
sta >LogFlag
pla
sta >LogFacility
phy
phx
plb
rtl
end
syslog_dat privdata libc_gen__
LogTag ds 4
TagLen ds 2
LogFlag ds 2
LogMask ds 2
LogFacility ds 2
memid ds 2
Xsyslog dc i'0,0,1,0,Xthis-Xsyslog'
Xthis anop
fmt dc c'[%u] ',h'0'
portname dc c'syslogd'
ptrtozero dc h'0'
nlonly dc h'01 00 0d'
end

146
lib/libc/gen/syslog2.mac Normal file
View File

@ -0,0 +1,146 @@
macro
&lab ~DisposeHandle &p1
&lab ph4 &p1
ldx #$1002
jsl $E10000
mend
macro
&lab ~NewHandle &p1,&p2,&p3,&p4
&lab ph4 &p1
ph2 &p2
ph2 &p2
ph4 &p4
ldx #$0902
jsl $E10000
mend
macro
&l long &a,&b
lclb &i
lclb &m
&a amid &a,1,1
&m setb ("&a"="M").or.("&a"="m")
&i setb ("&a"="I").or.("&a"="i")
aif c:&b=0,.a
&b amid &b,1,1
&m setb ("&b"="M").or.("&b"="m").or.&m
&i setb ("&b"="I").or.("&b"="i").or.&i
.a
&l rep #&m*32+&i*16
aif .not.&m,.b
longa on
.b
aif .not.&i,.c
longi on
.c
mend
macro
&l ph2 &n1
aif "&n1"="*",.f
lclc &c
&l anop
&c amid &n1,1,1
aif "&c"="#",.d
aif s:longa=1,.a
rep #%00100000
.a
aif "&c"<>"{",.b
&c amid &n1,l:&n1,1
aif "&c"<>"}",.g
&n1 amid &n1,2,l:&n1-2
lda (&n1)
pha
ago .e
.b
aif "&c"="<",.c
lda &n1
pha
ago .e
.c
&n1 amid &n1,2,l:&n1-1
pei &n1
ago .e
.d
&n1 amid &n1,2,l:&n1-1
pea &n1
ago .f
.e
aif s:longa=1,.f
sep #%00100000
.f
mexit
.g
mnote "Missing closing '}'",16
mend
macro
&l ph4 &n1
aif "&n1"="*",.f
lclc &c
&l anop
&c amid &n1,1,1
aif "&c"="#",.d
aif s:longa=1,.a
rep #%00100000
.a
aif "&c"<>"{",.b
&c amid &n1,l:&n1,1
aif "&c"<>"}",.g
&n1 amid &n1,2,l:&n1-2
ldy #2
lda (&n1),y
pha
lda (&n1)
pha
ago .e
.b
aif "&c"<>"[",.c
ldy #2
lda &n1,y
pha
lda &n1
pha
ago .e
.c
aif "&c"<>"<",.c1
&n1 amid &n1,2,l:&n1-1
pei &n1+2
pei &n1
ago .e
.c1
lda &n1+2
pha
lda &n1
pha
ago .e
.d
&n1 amid &n1,2,l:&n1-1
pea +(&n1)|-16
pea &n1
ago .f
.e
aif s:longa=1,.f
sep #%00100000
.f
mexit
.g
mnote "Missing closing '}'",16
mend
macro
&l short &a,&b
lclb &i
lclb &m
&a amid &a,1,1
&m setb ("&a"="M").or.("&a"="m")
&i setb ("&a"="I").or.("&a"="i")
aif c:&b=0,.a
&b amid &b,1,1
&m setb ("&b"="M").or.("&b"="m").or.&m
&i setb ("&b"="I").or.("&b"="i").or.&i
.a
&l sep #&m*32+&i*16
aif .not.&m,.b
longa off
.b
aif .not.&i,.c
longi off
.c
mend

124
lib/libc/gen/tty.c Normal file
View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This file is formatted with tab stops every 8 columns.
*
* $Id: tty.c,v 1.1 1997/02/28 05:12:45 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)ttyslot.c 5.6 (Berkeley) 2/23/91";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <types.h>
#include <ttyent.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <gsos.h>
/*
* gdr: ttyslot is probably buggy -- there is a search for '/' but
* not for ':'
*/
int
ttyslot(void) {
register struct ttyent *ttyp;
register int slot;
register char *p;
int cnt;
char *name;
setttyent();
for (cnt = 0; cnt < 3; ++cnt)
if (name = ttyname(cnt)) {
if (p = rindex(name, '/'))
++p;
else
p = name;
/*printf("p: %s\n",p);*/
for (slot = 1; ttyp = getttyent(); ++slot){
/*printf("ty_name: %s\n",ttyp->ty_name);*/
if (!strcmp(ttyp->ty_name, p)) {
endttyent();
return(slot);
} }
break;
}
endttyent();
return(0);
}
char *
ttyname(int fino) {
static ResultBuf32 resBuf;
static RefInfoRecGS refInfo = {3,1,0,(ResultBuf255Ptr)&resBuf};
if (!isatty(fino)) {
return NULL;
}
resBuf.bufSize = 32;
refInfo.refNum = fino;
GetRefInfoGS(&refInfo);
refInfo.pathname->bufString.text
[refInfo.pathname->bufString.length] = 0;
return refInfo.pathname->bufString.text;
}
int
isatty(int filedes) {
struct stat sb;
if (fstat(filedes,&sb) == -1) {
return 0;
} else if (sb.st_mode & S_IFCHR) {
return 1;
} else {
return 0;
}
}

115
lib/libc/gen/utime.c Normal file
View File

@ -0,0 +1,115 @@
/*
* utime, utimes. Implementation by Devin Reade.
*
* $Id: utime.c,v 1.1 1997/02/28 05:12:45 gdr Exp $
*
* This file is formatted with tab stops every 8 columns.
*/
#ifdef __ORCAC__
segment "libc_gen__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <sys/types.h>
#include <sys/time.h>
#include <utime.h>
#include <sys/errno.h>
#include <gno/gno.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include <gsos.h>
extern int _toolErr;
int
utime(const char *path, const struct utimbuf *buf)
{
FileInfoRecPtrGS infoPtr;
time_t t;
struct tm *tmptr;
int i;
/* allocate structures */
infoPtr = malloc (sizeof (FileInfoRecGS));
if (infoPtr == NULL) {
return -1;
}
infoPtr->pathname = (GSString255Ptr) __C2GSMALLOC(path);
if (infoPtr->pathname == NULL) {
i = errno;
free(infoPtr);
errno = i;
return -1;
}
/* initialize structure and get current file info */
infoPtr->pCount = 7;
_toolErr = 0;
GetFileInfoGS(infoPtr);
if (_toolErr) {
i = _mapErr(_toolErr);
free(infoPtr->pathname);
free(infoPtr);
errno = i;
return -1;
}
/* change the file creation time */
if (buf == NULL) {
time(&t);
tmptr = localtime(&t);
} else {
tmptr = localtime(&(buf->actime));
}
infoPtr->createDateTime.second = tmptr->tm_sec;
infoPtr->createDateTime.minute = tmptr->tm_min;
infoPtr->createDateTime.hour = tmptr->tm_hour;
infoPtr->createDateTime.year = tmptr->tm_year;
infoPtr->createDateTime.day = tmptr->tm_mday;
infoPtr->createDateTime.month = tmptr->tm_mon;
infoPtr->createDateTime.weekDay = tmptr->tm_wday;
/* change the file modification time */
if (buf == NULL) {
infoPtr->modDateTime = infoPtr->createDateTime;
} else {
tmptr = localtime(&(buf->modtime));
infoPtr->modDateTime.second = tmptr->tm_sec;
infoPtr->modDateTime.minute = tmptr->tm_min;
infoPtr->modDateTime.hour = tmptr->tm_hour;
infoPtr->modDateTime.year = tmptr->tm_year;
infoPtr->modDateTime.day = tmptr->tm_mday;
infoPtr->modDateTime.month = tmptr->tm_mon;
infoPtr->modDateTime.weekDay = tmptr->tm_wday;
}
/* write the info to the filesystem */
infoPtr->storageType = 0x0000;
SetFileInfoGS(infoPtr);
i = (_toolErr) ? _mapErr(_toolErr) : 0;
free(infoPtr->pathname);
free(infoPtr);
if (i != 0) {
errno = i;
return -1;
}
return 0;
}
int
utimes (const char *path, const struct timeval *tvp) {
struct utimbuf tmpval;
if (tvp) {
tmpval.actime = tvp[0].tv_sec;
tmpval.modtime = tvp[1].tv_sec;
return utime(path, &tmpval);
} else {
return utime(path, NULL);
}
}

29
lib/libc/gno/Makefile Normal file
View File

@ -0,0 +1,29 @@
#
# Makefile for libc/gno
# Devin Reade, 1996
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:46 gdr Exp $
#
.INCLUDE: ../../const.mk
OBJ_ASM = gnocmd.o parsearg.o stack.o
OBJ_C = gnomisc.o gsstring.o map.o
OBJS = $(OBJ_ASM) $(OBJ_C)
MACROS_ORCA = $(ORCA_DIST)/OrcaInclude
MACRO_FILES = $(MACROS_ORCA)/m16.tools $(MACROS_ORCA)/m16.orca
build: $(OBJS)
stack.mac:
macgen -p stack.asm $@ $(MACRO_FILES)
clean clobber:
$(RM) -f $(OBJS) stack.mac
.INCLUDE: ../rules.mk
gnocmd.o:: gnocmd.mac
parsearg.o:: parsearg.mac
stack.o:: stack.mac

74
lib/libc/gno/gnocmd.asm Normal file
View File

@ -0,0 +1,74 @@
***********************************************************************
*
* GNO command startup
* Version 1.0a
* Written by Tim Meekins
* Copyright (C) 1991-1996 by Procyon, Inc.
*
* This function emulates the startup code of a C program for assembly
* language programmers.
*
* To use it, have your first segment immediately JML to this routine.
* Then, make sure you have a segment called main() which will take argv
* and argc on the stack.
*
* $Id: gnocmd.asm,v 1.1 1997/02/28 05:12:46 gdr Exp $
*
**************************************************************************
keep gnocmd
mcopy gnocmd.mac
dummy START ; ends up in .root file
END
~GNO_COMMAND START
argv equ 0
argc equ 4
phk
plb
sta ~USER_ID
sty ~COMMANDLINE
stx ~COMMANDLINE+2
jsl ~MM_INIT
ph4 ~COMMANDLINE
clc
tdc
adc #argv
pea 0
pha
jsl ~GNO_PARSEARG
sta argc
cmp #0
beq error
ora2 argv,argv+2,@a
beq error
pei (argc)
pei (argv+2)
pei (argv)
jsl main
pha ;save return value
pei (argv+2)
pei (argv)
pei (argc)
jsl ~GNO_FREEARG
pla
rtl
error ErrWriteCString #gnoerror
lda #1
rtl
gnoerror dc c'~GNO_COMMAND SYSTEM FAILURE!',h'0d0a00'
END

108
lib/libc/gno/gnocmd.mac Normal file
View File

@ -0,0 +1,108 @@
macro
&lab ph4 &parm
lclc &char
lclc &char1
lclc &char2
&lab anop
&char amid &parm,1,1
aif "&char"="#",.immediate
aif "&char"="@",.at
aif s:longa=1,.chk1
rep #%00100000
.chk1
aif "&char"<>"{",.chk2
&char amid &parm,l:&parm,1
aif "&char"<>"}",.error
&parm amid &parm,2,l:&parm-2
ldy #2
lda (&parm),y
pha
lda (&parm)
pha
ago .shorten
.chk2
aif "&char"<>"[",.absolute
ldy #2
lda &parm,y
pha
lda &parm
pha
ago .shorten
.absolute
lda &parm+2
pha
lda &parm
pha
ago .shorten
.at
&char1 amid &parm,2,1
&char2 setc &char1
ph&char1
aif l:&parm<3,.chk2a
&char2 amid &parm,3,1
.chk2a
ph&char2
ago .shorten
.immediate
&parm amid &parm,2,l:&parm-1
pea +(&parm)|-16
pea &parm
ago .done
.shorten
aif s:longa=1,.done
sep #%00100000
.done
mexit
.error
mnote "Missing closing '}'",16
mend
macro
&lab ErrWriteCString &a1
&lab ph4 &a1
Tool $210c
mend
macro
&lab tool &a1
&lab ldx #&a1
jsl $e10000
mend
macro
&lab ora2 &arg1,&arg2,&dest
&lab anop
lclc &char
&char amid &arg1,1,1
aif "&char"="@",.at1
lda &arg1
ago .add
.at1
&char amid &arg1,2,1
aif "&char"="x",.x1
aif "&char"="X",.x1
aif "&char"="y",.y1
aif "&char"="Y",.y1
ago .add
.x1
txa
ago .add
.y1
tya
.add
ora &arg2
&char amid &dest,1,1
aif "&char"="@",.at2
sta &dest
ago .b
.at2
&char amid &dest,2,1
aif "&char"="x",.x2
aif "&char"="X",.x2
aif "&char"="y",.y2
aif "&char"="Y",.y2
ago .b
.x2
tax
ago .b
.y2
tay
.b
mend

59
lib/libc/gno/gnomisc.c Normal file
View File

@ -0,0 +1,59 @@
/*
* $Id: gnomisc.c,v 1.1 1997/02/28 05:12:47 gdr Exp $
*
* This file is formatted with tabs every 8 characters.
*/
#ifdef __ORCAC__
segment "libc_gno__";
#endif
#pragma optimize 0 /* optimization breaks this file (79, 15 tried) */
#pragma debug 0
#pragma memorymodel 0
#include <sys/syslimits.h>
#include <unistd.h>
#include <gsos.h>
#include <gno/gno.h>
int
needsgno(void) {
kernStatus();
if (_toolErr) {
return 0;
} else {
return 1;
}
}
static char *unknown = "(unknown)";
static GetNameRecGS namerec = { 1, NULL };
char *
__prognameGS (void) {
namerec.pCount = 1;
if (namerec.dataBuffer == NULL) {
namerec.dataBuffer =
(ResultBuf255Ptr) GOchange (NULL, NAME_MAX, NULL);
if (namerec.dataBuffer == NULL) {
return unknown;
}
GetNameGS(&namerec);
if (_toolErr) {
GOfree(namerec.dataBuffer);
namerec.dataBuffer = NULL;
return unknown;
}
/* NULL-terminate it */
namerec.dataBuffer->bufString.text
[namerec.dataBuffer->bufString.length] = '\0';
}
return namerec.dataBuffer->bufString.text;
}
void
WriteGString (GSStringPtr gp) {
/* perhaps this should call WriteGS directly */
write(STDERR_FILENO, gp->text, gp->length);
}

194
lib/libc/gno/gsstring.c Normal file
View File

@ -0,0 +1,194 @@
/*
* Apple IIgs specific string handling routines.
*
* The routines GIinit, GOinit, GIchange, GOchange, the macros
* GIfree and GOfree (in <gsos.h>), and typdefs for the GSString
* and ResultBuf pointers (in <types.h>) come from Soenke Behrens'
* GSString library.
*
* __C2GSMALLOC, __GS2CMALLOC, and __GS2C were rewritten from spec
* from the GNO v2.0.4 libc(3) man page (with a change of argument and
* result types) by Devin Reade. __C2GS was written by Devin Reade.
*
* $Id: gsstring.c,v 1.1 1997/02/28 05:12:47 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_gno__";
#endif
#pragma optimize 0 /* 79 seems to work */
#pragma debug 0
#pragma memorymodel 0
#include <machine/limits.h>
#include <types.h>
#include <gno/gno.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/*
* Initialize a GSString structure by allocating memory for a string
* of length 'length'. The caller has to check for errors, if any
* occured, the returned ptr will be NULL.
*
* gdr:
* - Add space for an extra NULL byte in the text field.
* - Allow the user to specify a C string initializer.
*/
GSStringPtr
GIinit (word length, const char *str)
{
return GIchange(NULL, length, str);
}
/*
* Change the length of a GSString. Again, the caller has to check for errors,
* the returned ptr is NULL if any occured.
*
* gdr:
* - Add space for an extra NULL byte in the text field.
* - Allow the user to specify a C string initializer.
*/
GSStringPtr
GIchange (GSStringPtr original, word length, const char *str)
{
/* this depends on a well-behaved realloc when given the NULL ptr */
original = realloc (original, sizeof(word) + length + 1);
if (original == NULL) {
return NULL;
}
original->length = length;
if (str != NULL) {
/* can't walk off end of str, so don't use memcpy */
strncpy(original->text, str, length);
} else {
original->text[0] = '\0';
}
original->text[length] = '\0';
return original;
}
/*
* Initialize a ResultBuf structure by allocating memory for a string
* of length 'length'. The caller has to check for errors, if any
* occured, the returned ptr will be NULL.
*/
ResultBufPtr
GOinit (unsigned int length, const char *str)
{
return GOchange(NULL, length, str);
}
/*
* Change the length of the ResultBuf. Again, the caller has to check for
* errors, the function returns NULL if any occured.
*
* gdr:
* - Add space for an extra NULL byte in the text field.
* - Allow the user to specify a C string initializer.
*/
ResultBufPtr
GOchange (ResultBufPtr original, unsigned int length, const char *str)
{
size_t len, orglen;
ResultBufPtr result;
/* this depends on a well-behaved realloc when given the NULL ptr */
len = 2 * sizeof(word) + length;
orglen = (original) ? original->bufString.length : 0;
result = realloc (original, len + 1);
if (result == NULL) {
return NULL;
}
result->bufSize = len;
if (str != NULL) {
/* can't walk off end of str, so don't use memcpy */
len = strlen(str);
len = MIN(len, length);
result->bufString.length = len;
strncpy(result->bufString.text, str, len);
result->bufString.text[len] = '\0';
} else if (original == NULL) { /* && str == NULL */
result->bufString.length = 0;
result->bufString.text[0] = '\0';
} else if (length < orglen) {
result->bufString.length = length;
} /* else leave original GSStringPtr untouched */
result->bufString.text[length] = '\0';
return result;
}
/*
* reimplementations for the next three ...
*/
GSStringPtr
__C2GSMALLOC (const char *s) {
size_t len;
len = strlen(s);
if (len > USHRT_MAX - 1) {
errno = EINVAL;
return NULL;
}
return GIchange(NULL, len, s);
}
char *
__GS2CMALLOC (const GSStringPtr g) {
char *p;
if ((p = malloc(g->length + 1)) != NULL) {
strncpy(p, g->text, g->length);
p[g->length] = '\0';
}
return p;
}
char *
__GS2C (char *s, const GSStringPtr g) {
strncpy(s, g->text, g->length);
s[g->length] = '\0';
return s;
}
/*
* __C2GS
*
* Converts a null-terminated C string into a class 1 GS/OS string.
* Space for the GS/OS string must already be allocated, and the
* length of s must be less than USHRT_MAX chars.
*
* If the s is too long, __C2GS will return NULL, otherwise it will
* return the GS/OS string g.
*
* As a side effect, g->text will also be NULL-terminated.
*/
GSStringPtr
__C2GS(const char *s, GSStringPtr g)
{
size_t len;
len = strlen(s);
if (len > USHRT_MAX - 1) {
errno = EINVAL;
return NULL; /* the string won't fit */
}
g->length = len;
strncpy(g->text, s, len);
g->text[len] = '\0';
return g;
}

227
lib/libc/gno/map.c Normal file
View File

@ -0,0 +1,227 @@
/*
* libc/gno/map.c -- various mapping functions
*
* $Id: map.c,v 1.1 1997/02/28 05:12:47 gdr Exp $
*
* This file is formatted with tabstops every 8 columns
*/
#ifdef __ORCAC__
segment "libc_gno__";
#endif
#pragma optimize 0
#pragma memorymodel 0
#pragma debug 0
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <gno/gno.h>
/* needed only during debugging */
#include <stdio.h>
#define GS_READ 0x0001
#define GS_WRITE 0x0002
#define GS_INVISIBLE 0x0004
#define GS_BACKUP 0x0020
#define GS_RENAME 0x0040
#define GS_DESTROY 0x0080
#define GS_MASK 0xFF18 /* complement of bitwise-OR of above GS- values */
static int __fileModeEmulation = 1; /* do we emulate Unix mode parameters? */
/*
* _getModeEmulation
*/
int
_getModeEmulation (void) {
return __fileModeEmulation;
}
/*
* _setModeEmulation
*/
int
_setModeEmulation (int newval) {
int result;
result = __fileModeEmulation;
__fileModeEmulation = !(newval == 0);
return result;
}
/*
* _mapMode2GS -- Take a Unix mode and return the GS/OS equivalent.
*
* Devin Reade <gdr@myrias.com>
*/
mode_t
_mapMode2GS(mode_t oldmode) {
mode_t newmode = GS_BACKUP;
if (__fileModeEmulation == 0) {
return oldmode;
}
if (oldmode & S_IRUSR) {
newmode |= GS_READ;
}
if (oldmode & S_IWUSR) {
newmode |= GS_WRITE | GS_RENAME | GS_DESTROY;
}
return newmode;
}
/*
* _mapMode2Unix -- Take a GS/OS mode and return the Unix equivalent.
*
* Devin Reade <gdr@myrias.com>
*/
mode_t
_mapMode2Unix(mode_t oldmode) {
mode_t newmode = S_IXUSR | S_IXGRP | S_IXOTH;
int mask;
if (__fileModeEmulation == 0) {
return oldmode;
}
if (oldmode & GS_READ) {
newmode |= S_IRUSR | S_IRGRP | S_IROTH;
}
if ((oldmode & GS_WRITE) && (oldmode & GS_RENAME) &&
(oldmode & GS_DESTROY)) {
newmode |= S_IWUSR | S_IWGRP | S_IWOTH;
}
/* get the umask */
umask((mask = umask(0)));
return newmode & mask;
}
/*
* _setPathMapping -- control whether or not we map pathnames
*
* Devin Reade <gdr@myrias.com>
*/
static int __force_slash = 0; /* default: no pathname mapping */
int
_setPathMapping (int val) {
int previous = __force_slash;
__force_slash = (val != 0);
return previous;
}
int
_getPathMapping (void) {
return __force_slash;
}
/*
* _mapPath -- map all occurances of ':' to '/'
*
* Devin Reade <gdr@myrias.com>
*/
char *
_mapPath (char *pathname) {
char *p;
int foundSlash, foundColon;
if (! __force_slash) {
return pathname;
}
/* validity check */
foundSlash = foundColon = 0;
for (p = pathname; *p != '\0'; p++) {
if (*p == ':') foundColon = 1;
if (*p == '/') foundSlash = 1;
}
if (foundSlash && foundColon) {
return NULL;
}
for (p = pathname; *p != '\0'; p++) {
if (*p == ':') *p = '/';
}
return pathname;
}
/*
* _mapPathGS -- map all occurances of ':' to '/'
*
* Devin Reade <gdr@myrias.com>
*/
GSStringPtr
_mapPathGS (GSStringPtr pathname) {
char *p, *q;
int foundSlash, foundColon;
if (! __force_slash || pathname->length == 0) {
return pathname;
}
/* validity check */
foundSlash = foundColon = 0;
p = pathname->text;
q = p + pathname->length;
while (p < q) {
if (*p == ':') foundColon = 1;
if (*p == '/') foundSlash = 1;
p++;
}
if (foundSlash && foundColon) {
return NULL;
}
p = pathname->text;
while (p < q) {
if (*p == ':') *p = '/';
p++;
}
return pathname;
}
/*
* _mapErr -- Take a GS/OS error and maps it to a kernel errno. If there
* is no direct mapping, then map it to EIO.
*/
int
_mapErr (int err) {
if (!err) {
return 0;
}
if ((err & 0xff00) == 0x4300) {
/* GNO already mapped the error */
return (err & 0x00ff);
}
switch (err) {
case 0x43: return EBADF;
case 0x44:
case 0x45:
case 0x46: return ENOENT;
case 0x47: return EEXIST;
case 0x48:
case 0x49: return ENOSPC;
case 0x4A: return ENOTDIR;
case 0x4B:
case 0x4F:
case 0x53: return EINVAL;
case 0x54: return ENOMEM;
case 0x4E: return EACCES;
case 0x58: return ENOTBLK;
default: return EIO;
}
}

329
lib/libc/gno/parsearg.asm Normal file
View File

@ -0,0 +1,329 @@
***********************************************************************
*
* GNO command-line parser
* Version 1.0b
* Written by Tim Meekins
* Copyright (C) 1991-1996 by Procyon, Inc.
*
* This function will take the command-line passed to a utility and parse
* it into an argv,argc structure like those used in C programs. This
* was written NOT as a replacement for a C parser, but for use by assembly
* language programmers writing shell commands.
*
* This function ASSUMES that the ByteWorks Memory Manager has been started
* up and is usable. This will eventually be superceded by the GNO Memory
* Management library.
*
* This function is based on actual GNO/ME shell (gsh) parsing code.
*
* $Id: parsearg.asm,v 1.1 1997/02/28 05:12:47 gdr Exp $
*
**************************************************************************
keep parsearg
mcopy parsearg.mac
dummy START ; ends up in .root
END
**************************************************************************
*
* Parse a single command
*
**************************************************************************
~GNO_PARSEARG START
;
; TOKENS used by the parser
;
T_WORD equ 1
T_EOF equ 2
MAXARG equ 256
;
; What state is the lexical analyzer in
;
NEUTRAL equ 0 ;a neutral state, get anything
INQUOTE equ 1 ;parsing a quoted string
INWORD equ 2 ;parsing a word
SINGQUOTE equ 3 ;single quote string
;
; local variables and function parameters
;
ptr equ 1
ch equ ptr+4
state equ ch+2
buf equ state+2
argv equ buf+4
word equ argv+4
temp equ word+4
argc equ temp+4
space equ argc+2
argptr equ space+3
commandline equ argptr+4
end equ commandline+4
; subroutine (4:commandline,4:argptr),space
tsc
sec
sbc #space-1
tcs
phd
tcd
add4 commandline,#8,buf
ph4 #1024
jsl ~NEW
sta word
stx word+2
ph4 #MAXARG*4
jsl ~NEW
sta argv
stx argv+2
ldy #2
sta [argptr]
txa
sta [argptr],y
stz argc
loop jsr gettoken
cmp #T_WORD
beq tok_word
jmp tok_eof
;
; Parse a word token
;
tok_word if2 argc,ne,#MAXARG,word1
jmp done
word1 anop
ldy #0
lenloop lda [word],y
iny
and #$FF
bne lenloop
pea 0
phy
jsl ~NEW
sta temp
stx temp+2
ora temp+2
bne word2
jmp error
word2 lda argc ;Copy word to argv[argc]
asl2 a
tay
lda temp
sta [argv],y
lda temp+2
iny2
sta [argv],y
ldy #0
short a
copyloop lda [word],y
sta [temp],y
iny
cmp #0
bne copyloop
long a
inc argc ;increment argument count
jmp loop
;
; Parse a command terminator
;
tok_eof anop
lda argc
asl2 a
tay
lda #0
sta [argv],y
iny2
sta [argv],y
pei (word+2)
pei (word)
jsl ~DISPOSE
done ldy argc
exit lda space
sta end-3
lda space+1
sta end-2
pld
tsc
clc
adc #end-4
tcs
tya
rtl
error anop
ldy #0
jmp exit
;=====================================================================
;
; lexical stage, return the next token
;
;=====================================================================
gettoken anop
mv4 word,ptr
;
; start in the neutral state
;
ld2 NEUTRAL,state
;
; the main loop
;
lexloop lda [buf]
inc buf
and2 @a,#$FF,ch
bne switch
if2 state,ne,#INWORD,loop2
jmp endword
loop2 lda #T_EOF
jmp lexdone
;
; jump to the current state
;
switch lda state
asl a
tax
jmp (statetbl,x)
statetbl dc a2'case_neutral'
dc a2'case_inquote'
dc a2'case_inword'
dc a2'case_single'
;
; CASE NEUTRAL
;
case_neutral if2 ch,eq,#' ',lexloop ;space
if2 @a,eq,#9,lexloop ;tab
if2 @a,ne,#13,neut4 ;return
lda #T_EOF
jmp lexdone
neut4 if2 @a,ne,#0,neut5 ;EOF
lda #T_EOF
jmp lexdone
neut5 if2 @a,ne,#'"',neut7
startquote lda #INQUOTE
bra neut10
neut7 if2 @a,ne,#"'",neut8
startsingle lda #SINGQUOTE
bra neut10
neut8 if2 @a,ne,#'\',neut9
lda [buf]
and #$FF
inc buf
neut9 sta [ptr] ;default
inc ptr
lda #INWORD
neut10 sta state
jmp lexloop
;
; CASE INQUOTE
;
case_inquote if2 ch,ne,#'\',quote2 ;is it a quoted character?
lda [buf]
inc buf
putword sta [ptr]
inc ptr
jmp lexloop
quote2 if2 @a,ne,#'"',putword
ld2 INWORD,state
jmp lexloop
;
; CASE SINGLEQUOTE
;
case_single anop
if2 ch,ne,#"'",putword
ld2 INWORD,state
jmp lexloop
;
; CASE INWORD
;
case_inword if2 ch,eq,#000,endword
if2 @a,eq,#' ',endword
if2 @a,eq,#009,endword
if2 @a,eq,#013,endword
cmp #'"'
jeq startquote
cmp #"'"
jeq startsingle
if2 @a,ne,#'\',putword
lda [buf]
inc buf
bra putword
endword dec buf
finiword lda #0
sta [ptr]
lda #T_WORD
lexdone rts
END
**************************************************************************
*
* Free the argv[] list
*
**************************************************************************
~GNO_FREEARG START
space equ 1
argc equ space+3
argv equ argc+2
end equ argv+4
; subroutine (4:argv,2:argc),space
tsc
phd
tcd
ldy #0
loop lda argc
beq done
dec argc
lda [argv],y
tax
iny2
lda [argv],y
iny2
phy
pha
phx
jsl ~DISPOSE
ply
bra loop
done pei (argv+2)
pei (argv)
jsl ~DISPOSE
lda space
sta end-3
lda space+1
sta end-2
pld
tsc
clc
adc #end-4
tcs
rtl
END

263
lib/libc/gno/parsearg.mac Normal file
View File

@ -0,0 +1,263 @@
macro
&lab ph4 &parm
lclc &char
lclc &char1
lclc &char2
&lab anop
&char amid &parm,1,1
aif "&char"="#",.immediate
aif "&char"="@",.at
aif s:longa=1,.chk1
rep #%00100000
.chk1
aif "&char"<>"{",.chk2
&char amid &parm,l:&parm,1
aif "&char"<>"}",.error
&parm amid &parm,2,l:&parm-2
ldy #2
lda (&parm),y
pha
lda (&parm)
pha
ago .shorten
.chk2
aif "&char"<>"[",.absolute
ldy #2
lda &parm,y
pha
lda &parm
pha
ago .shorten
.absolute
lda &parm+2
pha
lda &parm
pha
ago .shorten
.at
&char1 amid &parm,2,1
&char2 setc &char1
ph&char1
aif l:&parm<3,.chk2a
&char2 amid &parm,3,1
.chk2a
ph&char2
ago .shorten
.immediate
&parm amid &parm,2,l:&parm-1
pea +(&parm)|-16
pea &parm
ago .done
.shorten
aif s:longa=1,.done
sep #%00100000
.done
mexit
.error
mnote "Missing closing '}'",16
mend
macro
&lab LD2 &val,&adr
&lab lcla &count
lda #&val
&count seta 1
.loop
sta &adr(&count)
&count seta &count+1
aif &count>c:&adr,.done
ago ^loop
.done
mend
macro
&lab MV4 &src,&adr
&lab lcla &count
lda &src
&count seta 1
.loop1
sta &adr(&count)
&count seta &count+1
aif &count>c:&adr,.part2
ago ^loop1
.part2
lda &src+2
&count seta 1
.loop2
sta &adr(&count)+2
&count seta &count+1
aif &count>c:&adr,.done
ago ^loop2
.done
mend
macro
&lab long &stat
&lab anop
lcla &t
lcla &len
lclc &ch
&t seta 0
&len seta l:&stat
.a
aif &len=0,.b
&ch amid &stat,&len,1
aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i
aif ("&ch"="a").or.("&ch"="m"),.m
.c
&len seta &len-1
ago ^a
.i
longi on
&t seta &t+16
ago ^c
.m
longa on
&t seta &t+32
ago ^c
.b
aif &t=0,.d
rep #&t
.d
mend
macro
&lab short &stat
&lab anop
lcla &t
lcla &len
lclc &ch
&t seta 0
&len seta l:&stat
.a
aif &len=0,.b
&ch amid &stat,&len,1
aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i
aif ("&ch"="a").or.("&ch"="m"),.m
.c
&len seta &len-1
ago ^a
.i
longi off
&t seta &t+16
ago ^c
.m
longa off
&t seta &t+32
ago ^c
.b
aif &t=0,.d
sep #&t
.d
mend
macro
&lab asl2 &a
&lab asl &a
asl &a
mend
macro
&lab iny2
&lab iny
iny
mend
macro
&lab and2 &arg1,&arg2,&dest
&lab anop
lclc &char
&char amid &arg1,1,1
aif "&char"="@",.at1
lda &arg1
ago .add
.at1
&char amid &arg1,2,1
aif "&char"="x",.x1
aif "&char"="X",.x1
aif "&char"="y",.y1
aif "&char"="Y",.y1
ago .add
.x1
txa
ago .add
.y1
tya
.add
and &arg2
&char amid &dest,1,1
aif "&char"="@",.at2
sta &dest
ago .b
.at2
&char amid &dest,2,1
aif "&char"="x",.x2
aif "&char"="X",.x2
aif "&char"="y",.y2
aif "&char"="Y",.y2
ago .b
.x2
tax
ago .b
.y2
tay
.b
mend
macro
&lab if2 &var,&rel,&val,&label
&lab ago .skip
ble
bgt
.skip
lclc &char1
lclc &char2
&char1 amid &var,1,1
&char2 amid &var,2,1
aif "&char1"="@",.index
lda &var
.cmp
cmp &val
ago .branch
.index
aif "&char2"="x",.x1
aif "&char2"="X",.x1
aif "&char2"="y",.y1
aif "&char2"="Y",.y1
ago ^cmp
.x1
cpx &val
ago .branch
.y1
cpy &val
.branch
&char1 amid &rel,1,1
aif "&char1"="@",.done
b&rel &label
.done
mend
macro
&lab bgt &loc
&lab beq *+4
bcs &loc
mend
macro
&lab ble &loc
&lab bcc &loc
beq &loc
mend
macro
&lab jeq &loc
&lab bne *+5
jmp &loc
mend
macro
&lab add4 &arg1,&arg2,&dest
&lab anop
lclc &ch
&ch amid &arg2,1,1
clc
lda &arg1
adc &arg2
sta &dest
lda &arg1+2
aif "&ch"="#",.a
adc &arg2+2
ago .b
.a
adc &arg2|-16
.b
sta &dest+2
mend

124
lib/libc/gno/stack.asm Normal file
View File

@ -0,0 +1,124 @@
;
; Stack checking routines by Phillip Vandry <vandry@cam.org>. Added
; to GNO by Devin Reade <gdr@myrias.com>. See the man page for details.
;
; $Id: stack.asm,v 1.1 1997/02/28 05:12:47 gdr Exp $
;
keep stack
mcopy stack.mac
case on
* This test function goes into "stack.ROOT", which is not used
main start
jsl _beginStackCheck
ldx #16
jsr recurse
jsl _endStackCheck
rtl
recurse dex
beq outs
jsr recurse
outs rts
end
_beginStackCheck start libc_gno__
using stack_str
phb
pha
pha
pea 0
phd
~FindHandle *
tsc
phd
tcd
pha
pha
pei 3
pei 1
~GetHandleSize *
pla
sta >stack_size
pla
lda [1]
* leave 256 bytes at the beginning for SANE
clc
adc #256
tay ; start of handle
sta >stack_loc
ldx #0
tsc
dec a
dec a
sta 3
pea 0
plb
plb
lppp anop
txa
and #%111
tax
lda >stack_str,x
sta |0,y
iny
inx
cpy 3
bcc lppp
pld
pla
pla
plb
rtl
end
_endStackCheck start libc_gno__
using stack_str
phb
pea 0
plb
plb
lda >stack_loc
tay
ldx #0
lda |0,y
cmp >stack_str,x
beq lp2
lda #$ffff ; gone over
bra terminate
lp2 anop
txa
and #%111
tax
lda |0,y
cmp >stack_str,x
bne gotend
inx
iny
bra lp2
gotend anop ; Y = Stack not used
tya
sec
sbc >stack_loc
pha
lda >stack_size
sec
sbc 1,s
ply
terminate plb
rtl
end
setcom 50
stack_str privdata libc_gno__
dc c'StackChkS'
stack_size ds 2
stack_loc ds 2
end

65
lib/libc/gno/stack.mac Normal file
View File

@ -0,0 +1,65 @@
macro
&l ~FindHandle &p1
&l ph4 &p1
ldx #$1A02
jsl $E10000
mend
macro
&l ~GetHandleSize &p1
&l ph4 &p1
ldx #$1802
jsl $E10000
mend
macro
&l ph4 &n1
&l anop
aif "&n1"="*",.f
lclc &c
&c amid &n1,1,1
aif "&c"="#",.d
aif s:longa=1,.a
rep #%00100000
.a
aif "&c"<>"{",.b
&c amid &n1,l:&n1,1
aif "&c"<>"}",.g
&n1 amid &n1,2,l:&n1-2
ldy #2
lda (&n1),y
pha
lda (&n1)
pha
ago .e
.b
aif "&c"<>"[",.c
ldy #2
lda &n1,y
pha
lda &n1
pha
ago .e
.c
aif "&c"<>"<",.c1
&n1 amid &n1,2,l:&n1-1
pei &n1+2
pei &n1
ago .e
.c1
lda &n1+2
pha
lda &n1
pha
ago .e
.d
&n1 amid &n1,2,l:&n1-1
pea +(&n1)|-16
pea &n1
ago .f
.e
aif s:longa=1,.f
sep #%00100000
.f
mexit
.g
mnote "Missing closing '}'",16
mend

11
lib/libc/locale/Makefile Normal file
View File

@ -0,0 +1,11 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:48 gdr Exp $
#
.INCLUDE: ../../const.mk
OBJS = table.o
default: $(OBJS)
.INCLUDE: ../rules.mk

8
lib/libc/locale/table.c Normal file
View File

@ -0,0 +1,8 @@
/*
* This is a dummy file for now. We need this definition so that
* code compiled with #pragma debug -1 will not have the symbol unresolved.
*/
#include <stdlib.h>
int __mb_cur_max = 1;

15
lib/libc/rules.mk Normal file
View File

@ -0,0 +1,15 @@
#
# Default rules for libc/gno (override of /usr/local/lib/startup.mk)
# Devin Reade, 1997
#
# $Id: rules.mk,v 1.1 1997/02/28 05:12:39 gdr Exp $
#
%.o: %.c
$(CC) -o $@ -c $(__OFLAG) $(CFLAGS) $<
# $(MAKELIB) -l $(LIBC) $(MAKELIBFLAGS) $@
%.o: %.asm
$(AS) -o $@ -c $(__OFLAG) $(ASFLAGS) $<
@$(RM) $*.root
# $(MAKELIB) -l $(LIBC) $(MAKELIBFLAGS) $@

11
lib/libc/stdio/Makefile Normal file
View File

@ -0,0 +1,11 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:49 gdr Exp $
#
.INCLUDE: ../../const.mk
OBJS = mktemp.o perror.o tempnam.o
default: $(OBJS)
.INCLUDE: ../rules.mk

140
lib/libc/stdio/mktemp.c Normal file
View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This file is formatted with tab stops every 8 columns
*
* $Id: mktemp.c,v 1.1 1997/02/28 05:12:49 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_stdio";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
static int _gettemp(char *path, int *doopen);
int
mkstemp(char *path)
{
int fd;
return (_gettemp(path, &fd) ? fd : -1);
}
char *
mktemp(char *path)
{
return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
}
static int
_gettemp(char *path, register int *doopen)
{
extern int errno;
register char *start, *trv;
struct stat sbuf;
u_int pid;
char savechar;
pid = getpid();
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
while (*--trv == 'X') {
*trv = (pid % 10) + '0';
pid /= 10;
}
/*
* check the target directory; if you have six X's and it
* doesn't exist this runs for a *very* long time.
*/
for (start = trv + 1;; --trv) {
if (trv <= path)
break;
if (*trv == '/' || *trv == ':') {
savechar = *trv;
*trv = '\0';
if (stat(path, &sbuf))
return(0);
if (!S_ISDIR(sbuf.st_mode)) {
errno = ENOTDIR;
return(0);
}
*trv = savechar;
break;
}
}
for (;;) {
if (doopen) {
if ((*doopen =
open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
return(1);
if (errno != EEXIST)
return(0);
}
else if (stat(path, &sbuf))
return(errno == ENOENT ? 1 : 0);
/* tricky little algorithm for backward compatibility */
for (trv = start;;) {
if (!*trv)
return(0);
if (*trv == 'z')
*trv++ = 'a';
else {
if (isdigit(*trv))
*trv = 'a';
else
++*trv;
break;
}
}
}
/*NOTREACHED*/
}

140
lib/libc/stdio/perror.c Normal file
View File

@ -0,0 +1,140 @@
/*
* Implementation by Devin Reade.
*
* $Id: perror.c,v 1.1 1997/02/28 05:12:49 gdr Exp $
*
* This file is formatted with tab stops every 8 columns.
*/
/* I have to do this until I can modify ORCALib */
#define sys_errlist _gno_sys_errlist
#define sys_nerr _gno_sys_nerr
#ifdef __ORCAC__
segment "libc_stdio";
#endif
#pragma databank 1
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <sys/errno.h> /* for ELAST */
#include <stdio.h> /* for remainder */
const char * const sys_errlist[] = {
/* the following are used by both GNO and the Orca/Shell */
"unknown error", /* 0 */
"domain error", /* 1 */
"result too large", /* 2 */
"not enough memory", /* 3 */
"no such file or directory", /* 4 */
"I/O error", /* 5 */
"invalid argument", /* 6 */
"bad file descriptor", /* 7 */
"too many open files", /* 8 */
"permission denied", /* 9 */
"file exists", /* 10 */
"no space left on device", /* 11 */
/* the following are GNO-specific */
"operation not permitted", /* 12 */
"no such process", /* 13 */
"interrupted system call", /* 14 */
"arg list too long", /* 15 */
"exec format error", /* 16 */
"no child processes", /* 17 */
"resource unavailable", /* 18 */
"not a directory", /* 19 */
"inappropriate ioctl for device", /* 20 */
"broken pipe", /* 21 */
"illegal seek", /* 22 */
"block device required", /* 23 */
"is a directory", /* 24 */
"not a socket", /* 25 */
"destination address required", /* 26 */
"message too long", /* 27 */
"wrong protocol for socket", /* 28 */
"protocol not available", /* 29 */
"protocol not supported", /* 30 */
"socket type not supported", /* 31 */
"operation not supported on socket", /* 32 */
"protocol family not supported", /* 33 */
"address family not supported", /* 34 */
"address already in use", /* 35 */
"can't assign requested address", /* 36 */
"network is down", /* 37 */
"network is unreachable", /* 38 */
"network dropped connection on reset", /* 39 */
"connection aborted", /* 40 */
"connection reset by peer", /* 41 */
"no buffer space available", /* 42 */
"socket is already connected", /* 43 */
"socket is not connected", /* 44 */
"can't send after socket shutdown", /* 45 */
"too many references: can't splice", /* 46 */
"connection timed out", /* 47 */
"connection refused", /* 48 */
"operation would block", /* 49 */
"operation now in progress", /* 50 */
"operation already in progress", /* 51 */
"bad address", /* 52 */
"no such device", /* 53 */
"host is down", /* 54 */
"no route to host", /* 55 */
#define SYS_NERR 56 /* 55 + 1 for zeroth entry */
};
#if (ELAST + 1 != SYS_NERR)
#error message table out of sync
#endif
const int
sys_nerr = SYS_NERR;
const char * const *
_errnoText = sys_errlist; /* backward compatible */
char *
strerror (int errnum)
{
/*
* the size of buff must be greater than
* strlen(sys_errlist[0]) + max number of digits in an int + 3
* == 13 + 5 + 3 == 21
*/
static char buff[30];
if (errnum > 0 || errnum < sys_nerr) {
return sys_errlist[errnum];
}
sprintf(buff, "unknown error: %d", errnum);
return buff;
}
/*
* This implementation of perror should be replaced with one similar to
* that for 4.4BSD, so that stdio doesn't need to get linked in.
*/
void
perror (char *s)
{
char *s1, *s2;
if (s == NULL) {
s1 = s2 = "";
} else {
s1 = s;
s2 = ": ";
}
if (errno <= 0 || errno >= sys_nerr) {
fprintf(stderr, "%s%s%s: %d\n", s1, s2, sys_errlist[0], errno);
} else {
fprintf(stderr,"%s%s%s\n", s1, s2, sys_errlist[errno]);
}
}

112
lib/libc/stdio/tempnam.c Normal file
View File

@ -0,0 +1,112 @@
/*
* Temporary file and filename routines.
*
* $Id: tempnam.c,v 1.1 1997/02/28 05:12:49 gdr Exp $
*
* This file is formatted with tab stops every 8 characters.
*/
#ifdef __ORCAC__
segment "libc_stdio";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define max(A,B) (((A)<(B))?(B):(A))
/*
* tempnam
*
* Generate a pathname for a temporary file.
*
* tempnam will select a directory for the temporary file by using the
* following criteria:
*
* If dir is not the NULL pointer, tempnam uses the pathname pointed to by
* dir as the directory,
*
* otherwise, tmpdir uses the value of the TMPDIR environment variable if
* the variable is defined,
*
* otherwise the directory defined by P_tmpdir in the stdio.h header file
* if that directory is writable by the caller,
*
* otherwise, tempnam will use "/tmp" as a last resort.
*/
static char seed[4]="AAA";
/*
* cpdir - copy <str> into <buf>, removing the trailing directory separator
* if necessary.
*/
static char *
cpdir(char *buf, char *str)
{
char *p, pbrk;
if(str != NULL) {
strcpy(buf, str);
p = buf + strlen(buf) -1;
pbrk = strchr(buf,':') ? ':' : '/'; /* for GS/OS */
if(*p == pbrk) *p = '\0';
}
return(buf);
}
/*
* tempnam
* dir -- use this directory please (if non-NULL)
* prefix -- use this (if non-NULL) as filename prefix
*/
char *
tempnam (const char *dir, const char *prefix)
{
register char *p, *q, *tmpdir, pbrk;
int tl=0, dl=0, pl;
/* create a buffer <p> that's as large as necessary */
pl = strlen(P_tmpdir);
if( (tmpdir = getenv("TMPDIR")) != NULL ) tl = strlen(tmpdir);
if( dir != NULL ) dl = strlen(dir);
if( (p = malloc((unsigned int)(max(max(dl,tl),pl)+16))) == NULL )
return(NULL);
*p = '\0';
#define PERM W_OK
if( (dl == 0) || (access( cpdir(p, dir), PERM) != 0) )
if( (tl == 0) || (access( cpdir(p, tmpdir), PERM) != 0) )
if( access( cpdir(p, P_tmpdir), PERM) != 0 )
if( access( cpdir(p, "/tmp"), PERM) != 0 )
return(NULL);
pbrk = strchr(p,':') ? ':' : '/';
q = p + strlen(p);
*q++ = pbrk;
*q = '\0';
if(prefix) {
*(p+strlen(p)+5) = '\0';
(void)strncat(p, prefix, 5);
}
strcat(p, seed);
strcat(p, "XXXXXX");
q = seed;
while(*q == 'Z') *q++ = 'A';
++*q;
if(*mktemp(p) == '\0') return(NULL);
return(p);
}

11
lib/libc/stdlib/Makefile Normal file
View File

@ -0,0 +1,11 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:49 gdr Exp $
#
.INCLUDE: ../../const.mk
OBJS = environ.o getopt.o getsubopt.o
default: $(OBJS)
.INCLUDE: ../rules.mk

689
lib/libc/stdlib/environ.c Normal file
View File

@ -0,0 +1,689 @@
/*
* These routines were written by Devin Reade for GNO 2.0.1.
*
* $Id: environ.c,v 1.1 1997/02/28 05:12:49 gdr Exp $
*
* This file is formatted with tab stops every 3 columns.
*/
#ifdef __ORCAC__
segment "libc_stdlb";
#endif
#pragma databank 1
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <stddef.h>
#include <types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <gsos.h>
#include <orca.h>
#include <shell.h>
typedef struct stackelm {
struct stackelm *next;
char **env;
} stack_elm;
char **environ = NULL;
static short __environ_initialized = 0;
static short __use_environ = 0;
static short __in_environInit = 0;
static stack_elm *env_stack = NULL;
static char *__findenv(const char *name, int *offset);
static char *getvar(const char *name);
static int setvar(char *name, const char *value);
static void unsetvar (const char *name);
/*
* int environPush(void);
*
* Pre: none
*
* Post: The current state of the shell variable list is saved. This
* affects both the internal and the list pointed to by environ.
*
* Returns 0 on success, -1 otherwise.
*/
int
environPush(void) {
stack_elm *p;
PushVariablesGSPB parmBlock;
parmBlock.pCount = 0;
PushVariablesGS(&parmBlock);
/* if we're not using environ, then we're finished */
if(!__use_environ) return 0;
/* push environ onto the environment stack */
if ((p = (stack_elm *) malloc (sizeof(stack_elm))) == NULL)
return -1;
p->next = env_stack;
env_stack = p;
env_stack->env = environ;
/* zero the new environment and initialize */
environ = NULL;
__environ_initialized = 0;
if (environInit() != 0) { /* environInit failed; restore old environ */
__environ_initialized = 1;
environ = env_stack->env;
p = env_stack;
env_stack = env_stack->next;
free(p);
return -1;
}
return 0;
}
/*
* void environPop(void);
*
* Pre: none
*
* Post: The shell variable list is restored to the state that it was in
* when the most recent environPush() call was made. This affects both
* the internal version, and the list pointed to by environ.
*/
void
environPop(void) {
stack_elm *s;
char **p, **q;
PushVariablesGSPB parmBlock;
parmBlock.pCount = 0;
PopVariablesGS(&parmBlock);
/* if we're not using environ, then we're finished */
if(!__use_environ) return;
if(!env_stack) return; /* empty stack */
/* restore environ to its previous value */
p = environ;
environ = (env_stack) ? env_stack->env : NULL;
s = env_stack;
env_stack = (env_stack) ? env_stack->next : NULL;
/* free up each element in the discarded environment */
q = p;
while (q && *q) {
free(*q);
q++;
}
/* free the discarded environment */
if (p) free(p);
/* free the discarded environment stack element */
if (s) free(s);
return;
}
/*
* static int setvar (char *name, const char *value);
*
* Purpose: to set shell variable <name> to <value>. This affects only
* the internal representation, not that of the environ variable.
*
* Pre: <name> and <value> are null-terminated strings
*
* Post: <name> is set to <value>. Returns 0 on success, -1 on failure
*
* Acknowledgements: This routine is modified from code written by
* Dave Tribby [ GEnie: D.TRIBBY Internet: tribby@cup.hp.com ]
* for the "evaluate" shell utility for the Orca shell. Used
* with permission.
*/
static int
setvar(char *name, const char *value) {
int error;
GSString255Ptr var_value; /* Holds variable sized string */
SetGSPB set_var_pb;
static GSString255 var_name;
/* Shell call requires three parameters */
set_var_pb.pCount = 3;
/* Create GSOS string that holds the name of the variable */
/* Truncate value if > size of GSString255 */
var_name.length = strlen(name);
if (var_name.length > sizeof(var_name.text)) {
var_name.length = sizeof(var_name.text);
strncpy(var_name.text, name, sizeof(var_name.text));
} else {
strcpy(var_name.text, name);
}
set_var_pb.name = &var_name;
/* Allocate a GS string large enough to hold the value */
var_value = (GSString255Ptr) malloc(strlen(value)+sizeof(Word));
if (var_value == NULL) return (-1);
var_value->length = strlen(value);
strcpy(var_value->text, value);
set_var_pb.value = var_value;
set_var_pb.export = 1;
/* Make the shell call to set the variable */
SetGS(&set_var_pb);
error = toolerror();
free (var_value);
if (error) {
return -1;
} else {
return 0;
}
} /* setvar */
/*
* static void unsetvar (const char *name);
*
* Pre: <name> points to the name of the shell variable to be deleted. It
* may have a trailing '='.
*
* Post: The variable is deleted from the shell's internal environment.
* Any further references to it will return a NULL pointer.
*/
static void
unsetvar (const char *name) {
UnsetVariableGSPB parmblock;
GSString255 parmname;
/*
** delete the internal version
*/
/* set up the parameters */
parmblock.pCount = 1;
parmblock.name = &parmname;
parmname.length = strlen(name);
if (parmname.length > 254) parmname.length = 254;
strncpy(parmname.text,name,parmname.length);
if (parmname.text[parmname.length -1] == '=') {
parmname.text[parmname.length -1] = (char) NULL;
} else {
parmname.text[parmname.length] = (char) NULL;
}
UnsetVariableGS(&parmblock);
return;
}
/*
* static char *getvar (const char *name);
*
* Purpose: to get the value of shell variable <name>, using the internal
* (not environ) representation.
*
* Pre: <name> is a null-terminated string
*
* Post: returns a pointer to the value of <name>. If the variable has
* not been set or if the program is executing from an environment
* where shell variables do not exist, a NULL value is returned.
*
* Acknowledgements: This routine is modified from code written by
* Dave Tribby [ GEnie: D.TRIBBY Internet: tribby@cup.hp.com ]
* for the "evaluate" shell utility for the Orca shell. Used
* with permission.
*/
static char *getvar(const char *name) {
ReadVariableGSPB get_var_pb;
static ResultBuf255 var_value;
static GSString255 var_name;
char *result;
int length;
/* Shell call requires three parameters */
get_var_pb.pCount = 3;
/* Create GSOS string that holds the name of the variable */
/* Truncate value if > size of GSString255 */
var_name.length = strlen(name);
if (var_name.length > sizeof(var_name.text)) {
var_name.length = sizeof(var_name.text);
strncpy(var_name.text, name, sizeof(var_name.text));
} else {
strcpy(var_name.text, name);
}
get_var_pb.name = &var_name;
/* initialize the result buffer */
var_value.bufSize = sizeof (GSString255);
get_var_pb.value = &var_value;
/* Make the shell call to get the variable */
ReadVariableGS(&get_var_pb);
/* failed if tool error or not for export */
if (toolerror() || (get_var_pb.export == 0)) return (NULL);
/* get length of variable value */
length = ((ResultBuf255Ptr) get_var_pb.value)->bufString.length;
/* failed if variable not defined (length zero) */
if (length == 0) return (NULL);
/* set the NULL terminator */
result = (((ResultBuf255Ptr) get_var_pb.value)->bufString.text);
result[length] = (char) NULL;
return (result);
} /* getvar */
/* int environInit (void)
*
* Purpose: to initialize environ. This need not be done if the calling
* program does not need to access environ directly [that is, if it
* restricts itself to using getenv(), setenv(), putenv(), and
* unsetenv() ]
*
* Pre: none
*
* Post: the environment environ is initialized, and contains entries for
* all defined internal shell variables. Returns 0 on success,
* non-zero otherwise.
*/
int environInit (void) {
static ReadIndexedGSPB parmBuffer;
static ResultBuf255 nameBuffer, valueBuffer;
unsigned int nameLength, valueLength;
char *name;
char *value;
/* make sure we only do this once */
if (__environ_initialized) return 0;
__environ_initialized = 1;
__use_environ = 1;
__in_environInit = 1;
/*
** initialize the parameter block
*/
parmBuffer.pCount = 4;
parmBuffer.index = 1;
nameBuffer.bufSize = sizeof (GSString255);
valueBuffer.bufSize = sizeof (GSString255);
parmBuffer.name = &nameBuffer;
parmBuffer.value = &valueBuffer;
/* get space for our name and value buffers */
name = (char *) malloc (255 * sizeof(char));
if (!name) {
__in_environInit = 0;
return 1;
}
value = (char *) malloc (255 * sizeof(char));
if (!value) {
free(name);
__in_environInit = 0;
return 1;
}
/*
** add each variable into environ as they appear in the shell
** environment
*/
ReadIndexedGS (&parmBuffer);
nameLength = nameBuffer.bufString.length;
while (nameLength != 0) {
valueLength = valueBuffer.bufString.length;
/* copy the name and value */
strncpy (name, nameBuffer.bufString.text, nameLength);
name[nameLength] = (char) NULL;
strncpy (value, valueBuffer.bufString.text, valueLength);
value[valueLength] = (char) NULL;
/* try to place it in environ */
if (setenv(name, value, 1) != 0) {
free(name);
free(value);
__in_environInit = 0;
return 1;
}
/* get the next shell variable and continue ... */
parmBuffer.index++;
ReadIndexedGS (&parmBuffer);
nameLength = nameBuffer.bufString.length;
}
free(name);
free(value);
__in_environInit = 0;
return 0;
} /* environInit() */
/*
* int putenv (const char *str)
*
* Purpose: Take a string of the form NAME=value and stick it into the
* environment.
*
* Pre: <str> is a null-terminated string of the form NAME=value
*
* Post: returns zero if successful. A non-zero value indicates that
* space to expand the environment pointer table could not be
* acquired; in this case, the string has not been added
*
* Warning:
* Certain naming restrictions may apply if the environment variable
* is referenced by shell programs
*/
int putenv (const char *str) {
char *name, *value;
size_t l_str;
int result;
/* get space for our buffer */
l_str = strlen(str);
name = (char *) malloc (l_str + 1);
if (!name) return -1;
strcpy(name,str);
/* replace the '=' with a null and set value */
for (value=name; (*value) && (*value != '='); value++);
if (*value == '=') { /* found the end of name */
*value = (char) NULL;
value++;
result = (*value) ? setenv(name,value,1) : -1;
} else {
result = -1;
}
free(name);
return result;
}
/*
* char *getenv (const char *NAME)
*
* Purpose: search the environment for a string of the format NAME=VALUE
*
* Pre: NAME is the name of the variable for which the value is to be
* retrieved. It may end with an extra '=' which is not part of the
* name.
*
* Post: returns a pointer to the value of NAME. If NAME is not defined, it
* returns NULL. getenv() is case sensitive to NAME.
*/
char *getenv(const char *name) {
char *result;
size_t length;
length = strlen(name);
if (!length) return NULL;
if(name[length-1] == '=') {
char *tmp_name;
if ((tmp_name = malloc(length+1)) == NULL) return NULL;
strcpy(tmp_name,name);
tmp_name[length-1] = (char) NULL;
result = getvar(tmp_name);
free(tmp_name);
} else {
result = getvar(name);
}
return result;
}
/*
* static char *__findenv(const char *name, int *offset);
*
* Pre: <name> is a null-terminated string, which may end with '='.
*
* Post: returns a pointer to the value associated with <name> in the
* environment, if any, else it returns NULL. Sets <offset> to
* be the offset of the name/value combination in the environmental
* array (environ), for use by setenv(3) and unsetenv(3). It
* explicitly removes '=' in argument <name>.
*
* Acknowledgements: This is based on UCB code; see the above legalese.
*/
static char *__findenv(const char *name, int *offset) {
unsigned int len;
char **P, *C;
if (environ==NULL) {
return NULL;
}
for (C = name, len = 0; *C && (*C != '='); C++, len++);
for (P = environ; *P; P++) {
if (!strncmp(*P, name, len)) {
C = *P + len;
if (*C == '=') {
*offset = P - environ;
C++;
return(C);
}
}
}
return(NULL);
}
/*
* int setenv (const char *name, const char *value, int rewrite);
*
* Pre: <name> is the name of the environment variable to be set with
* value <value>. <rewrite> is either unset (zero) or set (non-
* zero).
*
* Post: If <name> does not previously exist, then it is added to the
* environment with value <value>. If <name> has been previously
* set, then <rewrite> is tested: If <rewrite> is non-zero then
* the old value is replaced, otherwise the call has no effect.
*
* Returns zero on success or if <name> already exists and <rewrite>
* is not set. Returns -1 and sets errno on failure.
*/
int setenv (const char *name, const char *value, int rewrite) {
static int alloced; /* if allocated space before */
char *C;
size_t l_value, l_name;
int offset;
char *tmp_name;
char *tmp_str;
if (*value == '=') value++; /* ignore any prepended '=' in value */
l_name = strlen(name); /* get the string lengths */
l_value = strlen(value);
if(name[l_name-1] == '=') l_name--; /* ignore any appended '=' in name */
if ((l_name == 0) || (l_value == 0)) { /* bad args! */
errno = EINVAL;
return -1;
}
/*
** make a copy of the name
*/
tmp_name = (char *) malloc (l_name+1); /* allocate necessary memory */
if (tmp_name == NULL) return -1;
strncpy(tmp_name, name, l_name); /* do the copy */
tmp_name[l_name] = '\0';
/*
** make a string of the form name=value, if necessary
*/
if (__use_environ) { /* are we using the environ structure? */
tmp_str = (char *) malloc (l_name + l_value + 2);
if (!tmp_str) {
free(tmp_name);
errno = ENOMEM;
return -1;
}
strcpy (tmp_str,tmp_name);
strcat (tmp_str,"=");
strcat (tmp_str,value);
}
/*
** Change the internal version
*/
if ((!__in_environInit) && ((rewrite) || (getenv(tmp_name) == NULL))) {
if (setvar(tmp_name, value)) {
int tmp_err = errno;
free(tmp_name);
if (__use_environ) free(tmp_str);
errno = tmp_err;
return -1;
}
}
if (__use_environ==0) {
free(tmp_name);
return 0;
}
/*
** Change the external (environ) version
*/
C = __findenv(tmp_name, &offset); /* find if already exists */
if (C!=NULL) {
if (!rewrite) {
free(tmp_name);
free(tmp_str);
return 0;
}
if (strlen(C) >= l_value) { /* old larger; copy over */
while (*value) {
*C = *value;
C++;
value++;
}
free(tmp_name);
free(tmp_str);
return 0;
}
} else { /* not found; create new slot */
int cnt;
char **P;
cnt = 0;
if (environ) for (P = environ; *P; P++) cnt++;
if (alloced) { /* done before; just increase size */
P = (char **) realloc ((char *)environ,
(size_t)(sizeof(char *) * (cnt + 2)));
if (!P) { /* realloc failed */
unsetvar(tmp_name);
free(tmp_name);
free(tmp_str);
errno = ENOMEM;
return -1;
} else {
environ = P;
}
} else { /* first time; get new space */
alloced = 1; /* copy old entries into it */
P = (char **) malloc ((size_t) (sizeof(char *) * (cnt + 2)));
if (!P) {
unsetvar(tmp_name);
free(tmp_name);
free(tmp_str);
errno = ENOMEM;
return -1;
}
/*
* original was:
* bcopy(environ, P, cnt * sizeof(char *));
* changed so that we could use the standard Orca libraries
* for non-gno implementations.
*/
if (environ) memcpy(P, environ, cnt * sizeof(char *));
environ = P;
}
environ[cnt + 1] = NULL;
offset = cnt;
}
/* we've got the new slot, now add it in */
environ[offset] = tmp_str;
free(tmp_name);
return 0;
}
/*
* void unsetenv (const char *name);
*
* Pre: <name> points to the name of the shell variable to be deleted. It
* may have a trailing '='.
*
* Post: The variable is deleted. Any further references to it will return
* a NULL pointer. This routine unsets both the internal and, if it's
* initialized, the environ representations.
*
* Acknowledgements: Contains BSD code. See the above legalese.
*/
void unsetenv (const char *name) {
char **P;
int offset;
/*
** delete the internal version
*/
unsetvar(name);
if(!__use_environ) return;
/*
** delete the environ version, if necessary.
*/
while (__findenv(name, &offset)!=NULL) { /* if set multiple times */
free(environ[offset]);
for (P = &environ[offset];; P++)
if (!(*P = *(P + 1)))
break;
}
return;
}

135
lib/libc/stdlib/getopt.c Normal file
View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This file is formatted for tab stops every 8 characters.
*
* $Id: getopt.c,v 1.1 1997/02/28 05:12:49 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_stdlb";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gno/gno.h> /* needed for __prognameGS() */
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(int nargc, char * const *nargv, const char *ostr)
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (EOF);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
return (EOF);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means EOF.
*/
if (optopt == (int)'-')
return (EOF);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", __prognameGS(), optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
__prognameGS(), optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}
int
getopt_restart (void) {
optreset = 1;
optind = 1;
return 0;
}

113
lib/libc/stdlib/getsubopt.c Normal file
View File

@ -0,0 +1,113 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* This file is formatted for tab stops every 8 characters.
*
* $Id: getsubopt.c,v 1.1 1997/02/28 05:12:50 gdr Exp $
*/
#ifdef __ORCAC__
segment "libc_stdlb";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
/*
* The SVID interface to getsubopt provides no way of figuring out which
* part of the suboptions list wasn't matched. This makes error messages
* tricky... The extern variable suboptarg is a pointer to the token
* which didn't match.
*/
char *suboptarg;
int
getsubopt(register char **optionp, register char * const *tokens,
register char **valuep)
{
register int cnt;
register char *p;
suboptarg = *valuep = NULL;
if (!optionp || !*optionp)
return(-1);
/* skip leading white-space, commas */
for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
if (!*p) {
*optionp = p;
return(-1);
}
/* save the start of the token, and skip the rest of the token. */
for (suboptarg = p;
*++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
if (*p) {
/*
* If there's an equals sign, set the value pointer, and
* skip over the value part of the token. Terminate the
* token.
*/
if (*p == '=') {
*p = '\0';
for (*valuep = ++p;
*p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
if (*p)
*p++ = '\0';
} else
*p++ = '\0';
/* Skip any whitespace or commas after this token. */
for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
}
/* set optionp for next round. */
*optionp = p;
for (cnt = 0; *tokens; ++tokens, ++cnt)
if (!strcmp(suboptarg, *tokens))
return(cnt);
return(-1);
}

13
lib/libc/string/Makefile Normal file
View File

@ -0,0 +1,13 @@
#
# Makefile for libc/gen.
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:50 gdr Exp $
#
.INCLUDE: ../../const.mk
OBJS = case.o str.o
default: $(OBJS)
.INCLUDE: ../rules.mk

70
lib/libc/string/case.c Normal file
View File

@ -0,0 +1,70 @@
/*
* Implementation by Devin Reade
*
* $Id: case.c,v 1.1 1997/02/28 05:12:50 gdr Exp $
*
* This file is formatted with tab stops every 8 columns.
*/
#ifdef __ORCAC__
segment "libc_str__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <string.h>
#include <ctype.h>
#undef TOLOWER
#define TOLOWER(c) isupper(c) ? _tolower(c) : c
int
strcasecmp (const char *s1, const char *s2) {
unsigned int c1, c2;
for (;;) {
c1 = TOLOWER(*s1);
c2 = TOLOWER(*s2);
if (c1 == '\0' && c2 == '\0') {
return 0;
} else if (c1 == c2) {
s1++; s2++;
} else {
/* don't do subtraction -- see man page */
return (c1 > c2) ? 1 : -1;
}
}
}
int
strncasecmp (const char *s1, const char *s2, size_t n) {
unsigned int c1, c2;
size_t i;
for (i=0; i<n; i++) {
c1 = TOLOWER(*s1);
c2 = TOLOWER(*s2);
if (c1 == '\0' && c2 == '\0') {
return 0;
} else if (c1 == c2) {
s1++; s2++;
} else {
/* don't do subtraction -- see man page */
return (c1 > c2) ? 1 : -1;
}
}
return 0;
}
short
stricmp (const char *s1, const char *s2) {
return strcasecmp(s1, s2);
}
short
strincmp (const char *s1, const char *s2, unsigned n) {
return strncasecmp(s1, s2, n);
}

102
lib/libc/string/str.c Normal file
View File

@ -0,0 +1,102 @@
/*
* str.c
*
* Various string routines not available in OrcaLib. For an explanation
* of these functions, see the appropriate man page.
*
* $Id: str.c,v 1.1 1997/02/28 05:12:50 gdr Exp $
*
* This file is formatted with tabs in every 8 columns.
*/
#ifdef __ORCAC__
segment "libc_str__";
#endif
#pragma optimize 0
#pragma debug 0
#pragma memorymodel 0
#include <stdlib.h>
#include <string.h>
/*
* index
*/
char *
index(const char *a, int b)
{
return strchr(a,b);
}
/*
* rindex
*/
char *
rindex(const char *a, int b)
{
return strrchr(a,b);
}
/*
* strsep
*
* Get next token from string *stringp, where tokens are nonempty
* strings separated by characters from delim.
*
* Writes NULs into the string at *stringp to end tokens.
* delim need not remain constant from call to call.
* On return, *stringp points past the last NUL written (if there might
* be further tokens), or is NULL (if there are definitely no more tokens).
*
* If *stringp is NULL, strtoken returns NULL.
*/
char *
strsep(register char **stringp, register const char *delim)
{
register char *s;
register const char *spanp;
register int c, sc;
char *tok;
if ((s = *stringp) == NULL) {
return (NULL);
}
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0) {
s = NULL;
} else {
s[-1] = 0;
}
*stringp = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
/*
* strdup
*/
char *
strdup(const char *str)
{
size_t len;
char *buf;
len = strlen(str) + 1;
if ((buf = malloc(len)) == NULL) {
return NULL;
}
strcpy(buf, str);
return buf;
}

13
lib/libc/sys/Makefile Normal file
View File

@ -0,0 +1,13 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:50 gdr Exp $
#
.INCLUDE: ../../const.mk
OBJS = trap.o syscall.o exec.o
default: $(OBJS)
.INCLUDE: ../rules.mk
trap.o:: trap.mac

604
lib/libc/sys/exec.c Normal file
View File

@ -0,0 +1,604 @@
/*
* exec(2) library calls. Written as part of lenviron by Devin Reade
* for GNO v2.0.3. Incorporated into libc as of GNO v2.0.6.
*
* $Id: exec.c,v 1.1 1997/02/28 05:12:50 gdr Exp $
*
* This file is formatted with tabs every 3 columns. The remainder of
* the comments in this section are from the lenviron v1.1.3 implementation.
* Of course, the GNO distribution headers now reflect these changes.
*
*************************************************************************
*
* These calls will only work with the GNO kernel! They were tested with
* GNO v2.0.3 and later, but _might_ work with other versions.
*
* These have been implemented using the standard Unix declarations. In
* particular, the prototype for execve(2) does _not_ match that of
* Procyon's distribution of GNO v2.0.5 and earlier.
*
* If you wish to make use of the execve call as provided with the GNO
* v2.0.5 (and earlier) distribution, that call is still available as the
* function
*
* int _execve(const char *path, const char *params);
*
* Note that execle(2) is not currently implemented. exect(2) probably
* never will be so implemented.
*
* Note that the current version of gsh parses $PATH backwards for some
* reason. For consistency, execvp() and execlp() will do the same for now.
* If gsh gets fixed or if you switch to a shell that parses $PATH front-to-
* back, just undefine BACKWARDS within this file an recompile. The
* appropriate code has already been tested.
*/
#ifdef __ORCAC__
segment "libc_sys__";
#endif
#pragma debug 0
#pragma memorymodel 0
/*
* Use bits 0, 1, 2, 6 (== decimal 71) for optimization. In Orca/C v2.1.0,
* bits 4 and 5 are still reported to be buggy.
*
* Around variadic routines, we also add in optimization bit 3 (== 79).
*/
/* pragma optimize 71 */
#include <sys/types.h>
#include <types.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <orca.h>
#include <gno/gno.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#define PARMSGUESS 10 /* initial length of argv array in execl, execlp */
#define BACKWARDS /* undefine this for shells that parse $PATH */
/* front to back. gsh as of Dec 93 needs this */
/* defined. */
pascal int Kexecve(char *pathname, char *cmdline, int *errno)
inline(0x1D03,0xE10008);
/*
* int isRootPath(const char *name);
*
* Pre: <name> is a file name
*
* Post: Return TRUE if the name is the full specification of a path name
* to a file starting at the root of the file system, otherwise
* return FALSE. Note that no test for existence is carried out;
* this routine only judges whether or not the given name is a valid
* one file starting at the root of the file system.
*
* Caveat: Unlike the Unix filesystem, "/" is not recognised as a complete
* file (or directory) name. Therefore, it will return FALSE if the
* the name is one character long and isn't "*" or "@" or a digit.
*/
/* allowable start of full file/device/prefix names */
static char* PfxBrkStr = "/:0123456789.*@";
int
isRootPath(const char *name) {
char *p;
p = strchr(PfxBrkStr, *name);
if (p == NULL) return FALSE;
switch (*p) {
case '/': /* FALLTHROUGH */
case ':':
/* "zero" length volume/prefix names not allowed */
if (*(p+1) == '\0') return FALSE;
else return TRUE;
/* NOTREACHED */
case '.':
/* "zero" length volume/prefix names not allowed. "./" and ".:" fail */
switch (*(p+1)) {
case '\0': /* FALLTHROUGH */
case '/': /* FALLTHROUGH */
case ':':
return FALSE;
default:
return TRUE;
}
/* NOTREACHED */
case '*': /* FALLTHROUGH */
case '@':
switch (*(p+1)) {
case '\0': /* FALLTHROUGH */
case '/': /* FALLTHROUGH */
case ':':
return TRUE;
default:
return FALSE;
}
/* NOTREACHED */
default:
/* it must be starting with a digit */
return TRUE;
}
}
/*
* char *buildCmd (char *const *argv);
*
* Pre: argv is a pointer to an array of strings, ending with a NULL pointer
*
* Post: Returns a pointer to a string consisting of all of the elements of
* argv, delimited by single spaces. Returns NULL if memory for the
* string cannot be allocated. If argv[0] == NULL, buildCmd() will
* return a pointer to a zero-length string. If it returns NULL,
* errno is also set to ENOMEM.
*
* Any GS/OS prefix (numerical or otherwise) on argv[0] will be stripped.
*/
char *
buildCmd (char *const *argv) {
char *comdbuf; /* pointer to the command line buffer */
size_t comdsize; /* length of the command line buffer */
int i;
char *s; /* a temporary pointer */
char delim; /* delimiter for pathnames (':' or '/') */
/* allocate memory for command line */
comdsize = 1;
i = 0;
while (argv[i] != NULL) {
comdsize = comdsize + strlen(argv[i]) + 1;
i++;
}
if ((comdbuf = malloc (comdsize)) == NULL) return NULL;
/* build command line from argv */
i = 0;
if (argv[i] == NULL) {
comdbuf[0] = (char) NULL;
} else {
/* find delimiter */
delim = (strchr(argv[0],':') == NULL) ? '/' : ':';
/* drop leading prefix */
s = argv[i];
while (*s) s++;
while ((s>argv[i]) && (*s != delim)) s--;
if (*s==delim) s++;
strcpy(comdbuf,s);
i++;
while (argv[i] != NULL) {
strcat(comdbuf, " ");
strcat(comdbuf, argv[i]);
i++;
}
}
return comdbuf;
}
/* int _fileExists (const char *file, const char *path)
*
* Pre: file is a file name, path is a full legal directory name
*
* Post: Returns 1 if file is in path, returns 0 and errno set on failure.
* Possible errno values on return are 0, ENOMEM, and ENOENT.
*
* Notes: If <path> is a zero-length string (not NULL!), then existence
* of <file> will be tested based on <file> being a partial pathname.
*
* _fileExists() will also fail if file is either a full path name or
* a zero-length string.
*/
static int
_fileExists (const char *file, const char *path) {
static char *buffer = NULL;
static size_t buffersize = 0;
size_t pathlen, length;
char delim;
char *tp;
delim = (strchr(path,':') == NULL) ? '/' : ':'; /* find delimiter */
/* <file> is a full pathname or empty string? Fail! */
if ((*file == '\0') || (isRootPath(file))) {
errno = ENOENT;
return 0;
}
/* calculate length of path prefix and full pathname */
pathlen = strlen(path);
length = strlen(file) + pathlen + 2;
/*
* Allocate more mem for buffer, if necessary. This fragment's behavior
* is dependant on the implementation of realloc and is not necessarily
* portable. It assumes that realloc() called with a NULL pointer behaves
* the same as malloc().
*/
if (length > buffersize) {
tp = (char *) realloc (buffer, length);
if (tp == NULL) {
if (buffer) free (buffer);
buffer = NULL;
buffersize = 0;
errno = ENOMEM;
return 0;
}
buffer = tp;
}
strcpy(buffer,path); /* make copy of path, */
if (pathlen) {
if (buffer[pathlen-1] != delim) { /* delimiter and terminate */
buffer[pathlen] = delim;
buffer[pathlen+1] = '\0';
}
} else {
*buffer = '\0';
}
strcat(buffer,file);
if (access(buffer, F_OK) == 0) { /* file found */
errno = 0;
return 1;
} /* else ... */
errno = ENOENT;
return 0;
}
/*
* char *buildPath (const char *filename);
*
* Pre: <filename> is the name of the file which we wish to locate.
*
* Post: If <filename> resides within $PATH, then buildPath will return a
* malloc'd pointer to the full pathname of the file.
* If <filename> cannot be found with $PATH, buildPath the default
* which is to search "/bin", then "/usr/bin". On error, NULL is
* returned and errno is set either to ENOENT or ENOMEM, as appropriate.
*
* If <filename> is in fact a full pathname, then a pointer to a malloc'd
* copy of the filename is returned; in this case, no test for existence
* is done <filename> is considered to be a full pathname if it
* begins with any of '/', ':', '.', '@', '*', or a digit.
* If any of '/', ':', or '.' is the first character, the
* filename must have a length of at least two characters.
*
* Caveat: There is a conditional compilation in this function; gsh currently
* parses the $PATH variable backwards, so for compatibility buildPath
* will also do a backwards parse if BACKWARDS is defined. Otherwise,
* $PATH will be parsed front-to-back.
*/
char *
buildPath (const char *filename) {
char *pathptr; /* pointer to the PATH shell variable */
char *path; /* pointer to the current PATH token */
char *buffptr; /* where we will store the full pathname */
size_t pathlen; /* for calculating space for malloc() */
char delim[2]; /* delimiter for pathnames. */
/* Assumption: if a path doesn't */
/* contain any '/' chars, the */
/* delimiter is ':'. */
#ifdef BACKWARDS
static char *default_path = "/usr/bin /bin";
char *path_copy;
#else
static char *default_path = "/bin /usr/bin";
#endif
/*
* if for some weird and wonderful reason, filename is a full pathname,
* then just return a pointer to a copy of it. In this case no test
* for existence is done.
*/
if (isRootPath(filename)) {
buffptr = (char *) malloc (strlen(filename) + 1);
if (buffptr == NULL) return NULL;
strcpy (buffptr,filename);
return buffptr;
}
/* get the value of the PATH shell variable */
pathptr = getenv ("PATH");
if (pathptr == NULL || *pathptr == '\0') {
/* PATH doesn't exist -- use default */
pathptr = default_path;
}
/* define the pathname delimiter */
(strstr(pathptr,"/") == NULL) ? strcpy (delim, ":") : strcpy (delim, "/");
/*
* search paths for filename -- backwards or forwards as appropriate
*/
#ifdef BACKWARDS
/* make a copy of the path */
pathlen = strlen(pathptr) + 1;
if ((path_copy = (char *) malloc((size_t) strlen(pathptr) + 1))==NULL) {
errno = ENOMEM;
return NULL;
}
strcpy(path_copy,pathptr);
path = path_copy + pathlen;
/* look for the file */
while (path>=path_copy) {
while ((path>path_copy) && (*path != ' ')) path--;
if (path>path_copy) { /* not done parsing $PATH */
if (_fileExists(filename, path+1)) { /* found it! */
path++;
break;
} else { /* not found; terminate string and try again */
*path = '\0';
}
} else {
/*
* at this point, path points to either first listed directory or
* whitespace; check it
*/
if (isprint(*path) && _fileExists(filename, path)) { /* found it! */
break;
} else {
free(path_copy); /* not in $PATH; parse failed */
errno = ENOENT;
return NULL;
}
}
}
#else
path = strtok (pathptr, " ");
while (path != NULL) {
if (_fileExists(filename, path)) break;
path = strtok (NULL, NULL);
}
/* filename not within listed paths */
if (path == NULL) {
errno = ENOENT;
return NULL;
}
#endif /* BACKWARDS */
/* allocate the buffer */
pathlen = strlen(filename) + strlen(path) + 2;
if ((buffptr = malloc (pathlen)) == NULL) {
#ifdef BACKWARDS
free(path_copy);
#endif
return NULL;
}
/* build the full pathname */
strcpy (buffptr,path);
strcat (buffptr,delim);
strcat (buffptr,filename);
#ifdef BACKWARDS
free(path_copy);
#endif
return buffptr;
}
/*
* int buildEnv (char *const *envp);
*
* Pre: envp is a pointer to an array of strings of the format NAME=VALUE.
*
* Post: On success, the strings in envp are added to the environment via
* putenv(), and 0 is returned. Returns -1 and sets errno=ENOMEM
* on failure.
*/
int
buildEnv (char *const *envp) {
while (*envp != NULL) {
if (putenv(*envp) == -1) return -1;
envp++;
}
return 0;
}
/*
* This function provides the functionality of the execve() routine
* provided with the GNO distribution. Unfortunately, GNO's version
* uses a non-standard prototype. (That's why execve is given a
* different prototype in this library.
*/
#if 0 /* it resides in trap.asm */
int _execve(const char *path, const char *params) {
return(Kexecve(path, params, &errno));
}
#endif
/*
* exec -- this function has been obsoleted, but is provided for
* backward compatibility
*/
#pragma databank 1
static void
_exec_child (const char *filename, const char *cmdline) {
_execve(filename, cmdline);
_exit(-1);
}
#pragma databank 0
int
exec (const char *filename, const char *cmdline) {
return fork2 (_exec_child, 1024, 0, "forked child of exec(2)", 4,
filename, cmdline);
}
/*
* The next functions (execv, execvp, execve, execl, execlp) are as per
* their man page descriptions. On error, errno could be set to any of
* ENOMEM, EIO, ENOENT. Note that there is no execle; Orca/C pukes on
* its declaration.
*/
int
execv(const char *path, char * const *argv) {
char *comd;
/* BUG BUG BUG BUG! -- this should be using <path> ! */
/* build the command line */
if ((comd = buildCmd (argv)) == NULL) return -1;
/* execute it */
return (Kexecve(path, comd, &errno));
}
int
execvp(const char *file, char * const *argv) {
char *comd;
char *path;
/* build the path name, if necessary */
path = buildPath (file);
/* build the command line */
if ((comd = buildCmd (argv)) == NULL) return -1;
/* execute it */
return(Kexecve(path, comd, &errno));
}
int
execve (const char *path, char * const *argv, char * const *envp) {
char *comd;
/* build the command line */
if ((comd = buildCmd (argv)) == NULL) return -1;
/* build the environment */
if (buildEnv(envp) == -1) return -1;
/* execute it */
return(Kexecve(path, comd, &errno));
}
/* no stack repair code on variadic function definitions */
/* pragma optimize 79 */
#pragma optimize 8
#pragma debug 0
int
execl(const char *path, const char *arg, ...) {
va_list list;
char **argv;
char *p;
char **q;
int i=0;
size_t vect_length;
int result;
/* allocate memory for initial guess of number of parameters */
argv = (char **) malloc (sizeof(char *) * PARMSGUESS);
if (argv==NULL) return -1;
vect_length = PARMSGUESS;
/* build the array */
p = arg;
va_start (list, arg);
while (p && *p) {
argv[i] = p; i++;
p = va_arg(list, char* );
/* reallocate memory if necessary */
if (i>=vect_length) {
vect_length += PARMSGUESS;
q = (char **) realloc(argv,vect_length);
if (p == NULL) {
free(argv);
errno = ENOMEM;
return -1;
}
argv = q;
}
}
argv[i] = (char *) NULL;
va_end(list);
result = execv(path,argv);
/* execvp failed; free argv */
free(argv);
return result;
}
int
execlp(const char *file, const char *arg, ...) {
va_list list;
char **argv;
char *p;
char **q;
int i=0;
size_t vect_length;
int result;
/* allocate memory for initial guess of number of parameters */
argv = (char **) malloc (sizeof(char *) * PARMSGUESS);
if (argv==NULL) return -1;
vect_length = PARMSGUESS;
/* build the array */
p = arg;
va_start (list, arg);
while (p && *p) {
argv[i] = p; i++;
p = va_arg(list, char* );
/* reallocate memory if necessary */
if (i>=vect_length) {
vect_length += PARMSGUESS;
q = (char **) realloc(argv,vect_length);
if (p == NULL) {
free(argv);
errno = ENOMEM;
return -1;
}
argv = q;
}
}
argv[i] = (char *) NULL;
va_end(list);
result = execvp(file,argv);
/* execvp failed; free argv */
free(argv);
return result;
}

952
lib/libc/sys/syscall.c Normal file
View File

@ -0,0 +1,952 @@
/*
* libc/sys/syscall.c
*
* System Call (Trap) Interface. This file contains those functions
* which are in Chapter 2 but emulate system traps as opposed to directly
* trapping to the GNO kernel. The actual kernel trap calls are in trap.c
* There are also a few support routines in here.
*
* Unless otherwise specified, see the respective man pages for details
* about these routines.
*
* $Id: syscall.c,v 1.1 1997/02/28 05:12:51 gdr Exp $
*
* This file is formatted with tab stops every 3 columns.
*/
#ifdef __ORCAC__
segment "libc_sys__";
#endif
#pragma debug 0
#pragma memorymodel 0
/*
* Use bits 0, 1, 2, 6 (== decimal 71) for optimization. In Orca/C v2.1.0,
* bits 4 and 5 are still reported to be buggy.
*
* Around variadic routines, we also add in optimization bit 3 (== 79).
*/
/* pragma optimize 71 */
#include <sys/syslimits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <types.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <gsos.h>
#include <string.h>
#include <stdio.h>
#include <orca.h>
#include <limits.h>
#include <signal.h>
#include <gno/gno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/mount.h>
/*
* This is the maximum file name length allowed to be returned by GS/OS
* in these stubs.
*/
#define GSOS_NAME_MAX PATH_MAX
/* these are prototyped in the Orca/C manual, but not in any header */
extern pascal void SystemQuitFlags (unsigned int);
extern pascal void SystemQuitPath (GSStringPtr);
/* these are the access bits to the GS/OS Create call */
#define GSOS_READ 0x0001
#define GSOS_WRITE 0x0002
#define GSOS_INVISIBLE 0x0004
#define GSOS_BACKUP 0x0020
#define GSOS_RENAME 0x0040
#define GSOS_DESTROY 0x0080
/* file types and, for EXEC, the auxtype */
#define TXT 0x04 /* text file */
#define BIN 0x06 /* binary file */
#define EXE 0xB5 /* shell command */
#define DIR 0x0F /* directory */
#define S16 0xB3 /* system file (application) */
#define SRC 0xB0 /* SRC + EXEC = shell script */
#define EXEC 0x0006
/*
* _chdir
*
* chdir and fchdir are implemented in terms of this function. Note that
* <pathname> _might_ be changed by _chdir() -- if an error occurs setting
* prefix 0, then the length of <pathname> will be set to zero.
*/
static int
_chdir(GSStringPtr pathname) {
PrefixRecGS prefx;
struct { /* truncated version of GetFileInfoRec */
word pCount;
GSString255Ptr pathname;
word access;
word fileType;
longword auxType;
word storageType;
} shortFileInfo;
int err;
/* make sure it's a directory */
shortFileInfo.pCount = 5;
shortFileInfo.pathname = (GSString255Ptr) pathname;
GetFileInfoGS(&shortFileInfo);
if ((errno = _mapErr(_toolErr)) != 0) {
return -1;
}
if (shortFileInfo.storageType != 0x0d && /* subdirectory */
shortFileInfo.storageType != 0x0f) { /* volume directory */
errno = ENOTDIR;
return -1;
}
prefx.pCount = 2;
prefx.prefixNum = 8;
prefx.buffer.setPrefix = shortFileInfo.pathname;
SetPrefixGS(&prefx);
if ((errno = _mapErr(_toolErr)) != 0) {
return -1;
}
prefx.prefixNum = 0;
if (prefx.buffer.setPrefix->length < 64) {
SetPrefixGS(&prefx);
if (_toolErr == 0) {
return 0;
}
}
prefx.buffer.setPrefix->length = 0;
SetPrefixGS(&prefx);
return 0;
}
/*
* _setFdTranslation, _getFdTranslation
*
* Does newline translation occur for read/write calls on the specified
* file descriptor? Off by default. Returns previous value for the
* specified fd.
*
* If by any chance we manage to open more than OPEN_MAX files, then
* translation is always off for those file descriptors.
*/
static int fdTranslationTable[OPEN_MAX];
#define _getFdTranslation(fd) \
(((fd) >= 0) && ((fd) < OPEN_MAX) && fdTranslationTable[fd])
static int
_setFdTranslation(int fd, int isOn) {
int oldval;
if (fd < 0 || fd >= OPEN_MAX) {
return 0;
}
oldval = fdTranslationTable[fd];
fdTranslationTable[fd] = (isOn != 0);
return oldval;
}
/*
* _statfs
*
* _statfs is a routine common to both statfs and fstatfs. The first
* parameter, gstr, is a pointer to a GSString containing the pathname.
* Other than the type of the first argument, this call is identical
* to the regular definition of statfs.
*/
static int
_statfs (GSStringPtr gstr, struct statfs *buf) {
DevNumRecGS gd;
VolumeRecGS vo;
char printbuf[20]; /* device name in .dxx format */
int err;
/* get the volume number for the file name gstr */
gd.pCount = 2;
gd.devName = (GSString32Ptr) gstr; /* does this work with a pathname? */
GetDevNumberGS(&gd);
if (_toolErr) {
errno = _mapErr(_toolErr);
return -1;
}
/* get the other volume info */
vo.pCount = 6;
sprintf(printbuf,".d%d", gd.devNum);
vo.devName = (GSString32Ptr) __C2GSMALLOC(printbuf);
vo.volName = (ResultBuf255Ptr) GOinit(32, NULL);
VolumeGS(&vo);
err = _toolErr;
/* copy over our information */
buf->f_type = (long) vo.fileSysID; /* FST type */
buf->f_bsize = (long) vo.blockSize; /* size of blocks in filesystem */
buf->f_blocks = vo.totalBlocks; /* number of blocks on the volume */
buf->f_bfree = vo.freeBlocks; /* number of free blocks */
buf->f_bavail = vo.freeBlocks; /* none reserved for superuser */
buf->f_files = -1; /* undefined by this filesystem */
buf->f_ffree = -1; /* undefined by this filesystem */
buf->f_fsid.hi = 0;
buf->f_fsid.lo = gd.devNum; /* device number */
buf->f_spare[0] = -1;
buf->f_spare[1] = -1;
buf->f_spare[2] = -1;
buf->f_spare[3] = -1;
buf->f_spare[4] = -1;
buf->f_spare[5] = -1;
buf->f_spare[6] = -1;
/* clean up, set up return conditions */
GOfree(vo.volName);
free(vo.devName);
if (err) {
errno = _mapErr(err);
return -1;
}
return 0;
}
/*
* access -- a replacement for the GNO v2.0.4 one; this one will actually
* return 0 when testing X_OK on a directory.
*
* This function uses gotos. Too bad; sometimes it's more efficient.
*/
int
access (const char *name, int mode) {
FileInfoRecGS *recptr;
GSStringPtr gptr;
size_t len;
int i;
int result = 0;
/* verify validity of args */
if (!name || !*name) { /* for SYSV */
errno=ENOENT;
return -1;
}
len = strlen(name);
if (len >= USHRT_MAX || (mode & ~(R_OK|W_OK|X_OK|F_OK))) {
errno = EINVAL;
return -1;
}
/* allocate and initialize the GS/OS variables */
if ((gptr = GIinit(len, name)) == NULL) {
errno = ENOMEM;
return -1;
}
if ((recptr = malloc(sizeof(FileInfoRecGS))) == NULL) {
GIfree(gptr);
errno = ENOMEM;
return -1;
}
recptr->pCount = 4;
recptr->pathname = (GSString255Ptr) gptr;
/* get the info and check for errors */
GetFileInfoGS(recptr);
i = toolerror();
if (i) {
errno = _mapErr(i);
result = -1;
goto done;
}
/* check read permission */
if ((mode & R_OK) && !(recptr->access & GSOS_READ)) {
errno = EACCES;
result = -1;
goto done;
}
/* check write permission */
if ((mode & W_OK) &&
!((recptr->access & GSOS_WRITE) &&
(recptr->access & GSOS_RENAME) &&
(recptr->access & GSOS_DESTROY))) {
errno = EACCES;
result = -1;
goto done;
}
/*
* Check execute mode. This is true if:
* the file is a directory;
* the file is a shell command;
* the file is a shell script;
* the file is a S16 file;
* But NOT if
* the file is a SYS or other type of file.
*/
if ((mode & X_OK) &&
!((recptr->fileType == EXE) ||
(recptr->fileType == DIR) ||
(recptr->fileType == SRC && recptr->auxType == EXEC) ||
(recptr->fileType == S16))) {
errno = EACCES;
result = -1;
}
done:
GIfree(gptr);
free(recptr);
return result;
}
/*
* chdir
*/
int
chdir (const char *pathname) {
GSStringPtr pathnameGS;
int result, err;
if ((pathnameGS = __C2GSMALLOC(pathname)) == NULL) {
errno = ENOMEM;
return -1;
}
result = _chdir(pathnameGS);
err = errno;
free(pathnameGS);
if (result != 0) {
errno = err;
}
return result;
}
/*
* close
*/
int
close (int filds) {
int cl[2] = {1, filds};
int err;
_setFdTranslation(filds, 0);
CloseGS(cl);
if (_toolErr) {
errno = _mapErr(_toolErr);
return -1;
}
return 0;
}
/*
* creat
*/
int
creat(const char *path, mode_t mode) {
return open (path, O_CREAT | O_TRUNC | O_WRONLY, mode);
}
/*
* fchdir
*/
int
fchdir (int fd)
{
RefInfoRecGS inforec;
int err, result;
/* get the pathname based on the file descriptor */
inforec.pCount = 3;
inforec.refNum = fd;
inforec.pathname = (ResultBuf255Ptr) GOinit(GSOS_NAME_MAX, NULL);
GetRefInfoGS (&inforec);
if ((err = _mapErr(_toolErr)) != 0) {
GOfree(inforec.pathname);
errno = err;
return -1;
}
/* change directory */
result = _chdir((GSStringPtr) &inforec.pathname->bufString);
err = errno;
GOfree(inforec.pathname);
errno = err;
return result;
}
/*
* fstatfs
*/
int
fstatfs (int fd, struct statfs *buf)
{
RefInfoRecGS inforec;
int err, result;
/* get the pathname based on the file descriptor */
inforec.pCount = 3;
inforec.refNum = fd;
inforec.pathname = (ResultBuf255Ptr) GOinit(GSOS_NAME_MAX, NULL);
GetRefInfoGS (&inforec);
if ((err = _mapErr(_toolErr)) != 0) {
GOfree(inforec.pathname);
errno = err;
return -1;
}
/* _statfs does the rest */
result = _statfs((GSStringPtr) &inforec.pathname->bufString, buf);
err = errno;
GOfree(inforec.pathname);
errno = err;
return result;
}
/*
* fsync
*/
int
fsync(int fd) {
short ff[2];
ff[0] = 1;
ff[1] = fd;
FlushGS(ff);
if (_toolErr) {
errno = _mapErr(_toolErr);
return -1;
}
return 0;
}
/*
* ftruncate
*/
int
ftruncate(int fd, off_t length)
{
SetPositionRecGS p;
p.pCount = 3;
p.base = 0;
p.refNum = fd;
p.displacement = length;
SetEOFGS(&p);
if (_toolErr) {
errno = _mapErr(_toolErr);
return -1;
}
return 0;
}
/*
* getdtablesize
*/
int
getdtablesize (void) {
return OPEN_MAX;
}
/*
* getpgrp
*/
pid_t
getpgrp (void) {
return _getpgrp(getpid());
}
/*
* gettimeofday
*
* IIgs HACK! HACK! HACK! We need a real gettimeofday!
*/
int
gettimeofday (struct timeval *tp, struct timezone *tzp) {
tp->tv_sec = time(NULL);
tp->tv_usec = 0l;
}
/*
* lseek
*/
off_t
lseek(int filds, off_t offset, int whence) {
SetPositionRecGS s;
PositionRecGS m;
EOFRecGS e;
int err;
e.pCount = m.pCount = 2;
e.refNum = s.refNum = m.refNum = filds;
GetEOFGS(&e);
if (err = _mapErr(_toolErr)) {
errno = err;
return -1L;
}
GetMarkGS(&m);
s.pCount = 3;
s.base = 0;
switch (whence) {
case SEEK_SET: s.displacement = offset; break;
case SEEK_CUR: s.displacement = m.position + offset; break;
case SEEK_END: s.displacement = e.eof + offset; break;
default:
errno = EINVAL;
return -1L;
}
if (s.displacement < 0) {
errno = EINVAL;
return -1L;
}
if (s.displacement > e.eof) {
SetEOFGS(&s);
if (err = _mapErr(_toolErr)) {
errno = err;
return -1L;
}
}
SetMarkGS(&s);
if (err = _mapErr(_toolErr)) {
errno = err;
return -1L;
}
return s.displacement;
}
/*
* mkdir
*/
int
mkdir(char *dirname)
{
CreateRecGS cr;
int err;
cr.pCount = 5;
cr.pathname = (GSString255Ptr) __C2GSMALLOC(dirname);
if (cr.pathname == NULL) {
errno = ENOMEM;
return -1;
}
cr.access = 0xC3;
cr.fileType = 0x0F;
cr.auxType = 0L;
cr.storageType = 0x0D;
CreateGS(&cr);
err = _toolErr;
free(cr.pathname);
if (err) {
errno = _mapErr(err);
return -1;
}
errno = 0;
return 0;
}
/*
* raise
*/
int
raise (int sig) {
return kill (getpid(), sig);
}
/*
* read
*/
ssize_t
read (int filds, void *buf, size_t bytecount) {
IORecGS iorec = {4, filds, buf, (long) bytecount, 0L};
char *p;
size_t i;
int err;
ssize_t result;
/* read in the buffer */
ReadGS(&iorec);
if (_toolErr == 0 || _toolErr == 0x4C) {
result = (size_t) iorec.transferCount;
} else if (err = _mapErr(_toolErr)) {
errno = err;
return -1;
}
/* translate newlines if necessary */
if (_getFdTranslation(filds)) {
p = (char *) buf;
for (i = 0; i < result; i++, p++) {
if (*p == '\r') {
*p = '\n';
}
}
}
}
/*
* rexit
*/
void
rexit (int code) {
SystemQuitFlags (0x4000);
SystemQuitPath (NULL);
exit(code);
}
/*
* statfs
*/
int
statfs(char *path, struct statfs *buf) {
ExpandPathRecGS ep;
int err, result;
/* get the full pathname of this file */
ep.pCount = 3;
if ((ep.inputPath = (GSString255Ptr) __C2GSMALLOC(path)) == NULL) {
return -1;
}
ep.outputPath = (ResultBuf255Ptr) GOinit(GSOS_NAME_MAX, NULL);
if (ep.outputPath == NULL) {
err = errno;
free(ep.inputPath);
errno = err;
return -1;
}
ep.flags = 0;
ExpandPathGS(&ep);
if (_toolErr) {
result = -1;
err = _mapErr(_toolErr);
} else {
result = _statfs((GSStringPtr) &ep.outputPath->bufString, buf);
err = errno;
}
free(ep.inputPath);
GOfree(ep.outputPath);
errno = err;
return result;
}
/*
* truncate
*/
int
truncate(const char *path, off_t length)
{
SetPositionRecGS p;
int closerec[2];
struct {
Word pCount;
Word refNum;
GSStringPtr pathname;
Word requestAccess;
} openrec; /* abbreviated version of OpenRecGS */
int err, result;
/* open the file */
openrec.pCount = 3;
if ((openrec.pathname = __C2GSMALLOC(path)) == NULL) {
return -1;
}
openrec.requestAccess = readWriteEnable;
OpenGS(&openrec);
err = _mapErr(_toolErr);
free(openrec.pathname);
if (err) {
errno = err;
return -1;
}
/* set up the close block */
closerec[0] = 1;
closerec[1] = openrec.refNum;
p.pCount = 3;
p.base = 0;
p.refNum = openrec.refNum;
p.displacement = length;
SetEOFGS(&p);
if (_toolErr) {
errno = _mapErr(_toolErr);
result = -1;
} else {
result = 0;
}
CloseGS(closerec);
return result;
}
/*
* umask
*/
mode_t
umask (mode_t mask) {
static mode_t currentMask = 0xFFFF;
static int maskInitialized = 0;
char *p;
mode_t result;
char maskStr[5];
const char *umaskStr = "UMASK";
/* initialize off of environment first time through -- hack */
if (! maskInitialized) {
if ((p = getenv(umaskStr)) == NULL) {
currentMask = 022;
} else {
currentMask = strtoul(p, NULL, 8);
}
maskInitialized = 1;
}
result = currentMask;
currentMask = mask & 0777;
maskStr[0] = '0';
maskStr[1] = '0' + ((currentMask & 0700) >> 6);
maskStr[2] = '0' + ((currentMask & 0070) >> 3);
maskStr[3] = '0' + (currentMask & 0007);
maskStr[4] = '\0';
setenv(umaskStr, maskStr, 1); /* ignore errors */
return result;
}
/*
* unlink
*/
int unlink(char *fname)
{
/*
* Orca/C doesn't specify what the "non-zero" return code is, so
* force it to be -1.
*/
return (remove(fname) == 0) ? 0 : -1;
}
/*
* When GNO supports wait4(2) (and assuming that it doesn't have waitpid()),
* this routine can be changed to the following:
*
* return (wait4(pid, istat, options, (struct rusage *)0));
*
* This implementation is flawed since it's not done in the kernel. See
* the BUGS section of the man page for details.
*/
pid_t
waitpid(pid_t pid, union wait *istat, int options)
{
int result;
pid_t pgid;
#if 1
/*
* there's a note in <unistd.h> about the implementation of
* getpgrp() being buggy.
*/
if (pid < -1 || pid == 0) {
fprintf(stderr,"waitpid: process groups not implemented. Aborted.\n");
abort();
}
#endif
/* We really need to do this in the kernel. */
if (pid < -1) {
pgid = -pid;
} else if (pid == 0) {
pgid = _getpgrp(getpid());
} else {
pgid = -1;
}
for(;;) {
result = wait(istat);
if ((result == -1) ||
(pid == result) ||
((pgid > 1) && (pgid == _getpgrp(result)))) {
return result;
}
}
}
/*
* write
*/
ssize_t
write(int filds, void *buf, size_t bytecount) {
IORecGS iorec = {4, filds, buf, (long) bytecount, 0L};
int err;
size_t i;
char *p;
/* translate newlines if necessary */
if (_getFdTranslation(filds)) {
p = (char *) buf;
for (i = 0; i < bytecount; i++, p++) {
if (*p == '\n') {
*p = '\r';
}
}
}
/* write the file block */
WriteGS(&iorec);
if (err = _mapErr(_toolErr)) {
errno = err;
return -1;
}
return (size_t) iorec.transferCount;
}
/*
* open -- end of file because of higher optimization required
*/
/* pragma optimize 79 */
#pragma optimize 8
#pragma debug 0
int
open (const char *path, int oflag, ...) {
OpenRecGS openRec;
CreateRecGS createRec;
SetPositionRecGS setMarkRec;
va_list list;
mode_t openmode;
int err; /* saved errno */
int result; /* returned value */
size_t currentEof; /* saved eof nec for append */
/* grab extra parameter if necessary */
va_start(list, oflag);
if (oflag & O_CREAT) {
openmode = va_arg(list, mode_t);
}
err = 0;
/* try to open the file */
openRec.pCount = 12;
openRec.pathname = (GSString255Ptr) __C2GSMALLOC(path);
if (openRec.pathname == NULL) {
va_end(list);
errno = ENOMEM;
return -1; /* DON'T goto label 'done' ... spurious free() */
}
if ((oflag & O_ACCMODE) == O_RDONLY) {
openRec.requestAccess = readEnable;
} else if ((oflag & O_ACCMODE) == O_WRONLY) {
openRec.requestAccess = writeEnable;
} else if ((oflag & O_ACCMODE) == O_RDWR) {
openRec.requestAccess = readWriteEnable;
} else {
openRec.requestAccess = 0;
}
openRec.resourceNumber = 0; /* data fork */
openRec.optionList = NULL; /* no FST-specific info */
OpenGS(&openRec);
if ((_toolErr == 0) && (oflag & O_CREAT) && (oflag & O_EXCL)) {
/* file already existed */
close(openRec.refNum);
err = EEXIST;
result = -1;
goto done;
} else if ((_toolErr == 0) && (oflag & O_WRONLY) &&
(openRec.storageType == 0x0d || openRec.storageType == 0x0f)) {
/* opening a volume directory or subdirectory for writing not permitted */
close(openRec.refNum);
err = EISDIR;
result = -1;
goto done;
} else if ((err = _mapErr(_toolErr)) && (err == ENOENT)) {
/* file doesn't exist -- create? */
if (oflag & O_CREAT) {
createRec.pCount = 3;
createRec.pathname = openRec.pathname;
createRec.access = _mapMode2GS(openmode);
createRec.fileType = (oflag & O_BINARY) ? BIN : TXT;
CreateGS(&createRec);
if (err = _mapErr(_toolErr)) {
result = -1;
goto done;
}
OpenGS(&openRec);
if (err = _mapErr(_toolErr)) {
result = -1;
goto done;
}
} else {
/* no create and didn't exist -- error */
result = -1;
goto done;
}
} else if (err) {
/* unknown error on open */
result = -1;
goto done;
}
/* if we got here, the file is open */
currentEof = openRec.eof;
/* truncate the file if necessary */
if ((oflag & O_TRUNC) && ((oflag & O_ACCMODE) != O_RDONLY)) {
ftruncate(openRec.refNum, 0L);
currentEof = 0L;
}
/* append to file? */
if ((oflag & O_APPEND) && ((oflag & O_ACCMODE) != O_RDONLY)) {
setMarkRec.pCount = 3;
setMarkRec.refNum = openRec.refNum;
setMarkRec.base = 0;
setMarkRec.displacement = currentEof;
SetMarkGS(&setMarkRec);
if (err = _mapErr(_toolErr)) {
result = -1;
goto done;
}
}
/* success! */
err = 0;
result = openRec.refNum;
if (oflag & O_TRANS) {
_setFdTranslation(result, 1);
}
done:
free(openRec.pathname);
va_end(list);
errno = err;
return result;
}

1269
lib/libc/sys/trap.asm Normal file

File diff suppressed because it is too large Load Diff

251
lib/libc/sys/trap.mac Normal file
View File

@ -0,0 +1,251 @@
macro
&lab ph4 &parm
lclc &char
lclc &char1
lclc &char2
&lab anop
&char amid &parm,1,1
aif "&char"="#",.immediate
aif "&char"="@",.at
aif s:longa=1,.chk1
rep #%00100000
.chk1
aif "&char"<>"{",.chk2
&char amid &parm,l:&parm,1
aif "&char"<>"}",.error
&parm amid &parm,2,l:&parm-2
ldy #2
lda (&parm),y
pha
lda (&parm)
pha
ago .shorten
.chk2
aif "&char"<>"[",.absolute
ldy #2
lda &parm,y
pha
lda &parm
pha
ago .shorten
.absolute
lda &parm+2
pha
lda &parm
pha
ago .shorten
.at
&char1 amid &parm,2,1
&char2 setc &char1
ph&char1
aif l:&parm<3,.chk2a
&char2 amid &parm,3,1
.chk2a
ph&char2
ago .shorten
.immediate
&parm amid &parm,2,l:&parm-1
pea +(&parm)|-16
pea &parm
ago .done
.shorten
aif s:longa=1,.done
sep #%00100000
.done
mexit
.error
mnote "Missing closing '}'",16
mend
MACRO
&lab return2
&lab anop
.h
aif &totallen=0,.i
lda &worklen+1
sta &worklen+&totallen+1
lda &worklen
sta &worklen+&totallen
.i
plb
pld
tsc
clc
adc #&worklen+&totallen
tcs
tya
.j
rtl
mend
MACRO
&lab ph2 &parm
lclc &char
&lab anop
aif c:&parm=0,.done
&char amid &parm,1,1
aif "&char"="#",.immediate
aif "&char"="@",.at
aif s:longa=1,.chk
rep #%00100000
.chk
aif "&char"<>"{",.absolute
&char amid &parm,l:&parm,1
aif "&char"<>"}",.error
&parm amid &parm,2,l:&parm-2
lda (&parm)
pha
ago .shorten
.absolute
lda &parm
pha
ago .shorten
.immediate
&parm amid &parm,2,l:&parm-1
pea &parm
ago .done
.at
&char amid &parm,2,1
ph&char
.shorten
aif s:longa=1,.done
sep #%00100000
.done
mexit
.error
mnote "Missing closing '}'",16
mend
macro
&l ret &r
&l anop
lclc &len
aif c:&r,.a
lclc &r
&r setc 0
&len setc 0
ago .h
.a
&len amid &r,2,1
aif "&len"=":",.b
&len amid &r,1,2
&r amid &r,4,l:&r-3
ago .c
.b
&len amid &r,1,1
&r amid &r,3,l:&r-2
.c
aif &len<>2,.d
ldy &r
ago .h
.d
aif &len<>4,.e
ldx &r+2
ldy &r
ago .h
.e
aif &len<>10,.g
ldy #&r
ldx #^&r
ago .h
.g
mnote 'Not a valid return length',16
mexit
.h
aif &totallen=0,.i
lda &worklen+2
sta &worklen+&totallen+2
lda &worklen+1
sta &worklen+&totallen+1
.i
pld
tsc
clc
adc #&worklen+&totallen
tcs
aif &len=0,.j
tya
.j
rtl
mend
macro
&l sub &parms,&work
&l anop
aif c:&work,.a
lclc &work
&work setc 0
.a
gbla &totallen
gbla &worklen
&worklen seta &work
&totallen seta 0
aif c:&parms=0,.e
lclc &len
lclc &p
lcla &i
&i seta c:&parms
.b
&p setc &parms(&i)
&len amid &p,2,1
aif "&len"=":",.c
&len amid &p,1,2
&p amid &p,4,l:&p-3
ago .d
.c
&len amid &p,1,1
&p amid &p,3,l:&p-2
.d
&p equ &totallen+4+&work
&totallen seta &totallen+&len
&i seta &i-1
aif &i,^b
.e
tsc
aif &work=0,.f
sec
sbc #&work
tcs
.f
phd
tcd
mend
MACRO
&lab subroutine &parms,&work
&lab anop
aif c:&work,.a
lclc &work
&work setc 0
.a
gbla &totallen
gbla &worklen
&worklen seta &work
&totallen seta 0
aif c:&parms=0,.e
lclc &len
lclc &p
lcla &i
&i seta c:&parms
.b
&p setc &parms(&i)
&len amid &p,2,1
aif "&len"=":",.c
&len amid &p,1,2
&p amid &p,4,l:&p-3
ago .d
.c
&len amid &p,1,1
&p amid &p,3,l:&p-2
.d
&p equ &totallen+3+&work
&totallen seta &totallen+&len
&i seta &i-1
aif &i,^b
.e
tsc
sec
sbc #&work
tcs
inc a
phd
tcd
phb
phk
plb
mend

12
lib/libc/tests/Makefile Normal file
View File

@ -0,0 +1,12 @@
#
# Makefile for libc/tests.
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:51 gdr Exp $
#
.INCLUDE: ../const.mk
TESTS =
default: $(TESTS)
/bin/true

View File

@ -0,0 +1,15 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:51 gdr Exp $
#
.INCLUDE: ../../../const.mk
STACK =
LIBC := ../../libc
LDLIBS = -l$(LIBC)
CFLAGS := -v -w -G25 $(STACK) $(DEFINES) $(INCLUDES)
default: basename dirent envtest err getcwd getgrent scandir sleep
.PRECIOUS: basename dirent.o envtest.o err.o getcwd.o getgrent.o scandir.o \
sleep.o

View File

@ -0,0 +1,23 @@
/*
* Test by Devin Reade
*
* $Id: basename.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int
main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr,"usage: %s filename\n", argv[0]);
exit(1);
}
printf("basename(\"%s\") = \"%s\"\n", argv[1], basename(argv[1]));
printf("dirname(\"%s\") = \"%s\"\n", argv[1], dirname(argv[1]));
return 0;
}

View File

@ -0,0 +1,74 @@
/*
* Test by Devin Reade
*
* $Id: dirent.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*
*/
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#define FAIL(arg) { fprintf(stderr,"%s (errno==%d)\n", arg, errno); exit(1); }
int main (int argc, char **argv) {
DIR *dirp;
struct dirent *ent;
char *path;
int count;
long offset;
if (argc != 2) {
printf("usage: %s dir_name\n", argv[0]);
exit(1);
}
path = argv[1];
printf("opening %s\n", path);
/* test opendir */
if ((dirp = opendir(path)) == NULL) {
FAIL("opendir failed");
}
/* test dirfd */
printf("dirfd returns %d\n", dirfd(dirp));
/* test readdir and telldir */
count = 0;
printf("current offset is %ld\n", telldir(dirp));
while ((ent = readdir(dirp)) != NULL) {
printf("\t%lu %hu %hu %hu %s\n", ent->d_fileno,
ent->d_reclen, (unsigned short) ent->d_type,
(unsigned short) ent->d_namlen, ent->d_name);
if (count == 1) {
offset = telldir(dirp);
printf("count %d has offset %ld\n", count, offset);
}
count++;
}
/* test seekdir */
printf("seeking to saved offset\n");
seekdir(dirp, offset);
if ((ent = readdir(dirp)) != NULL) {
printf("\t%lu %hu %hu %hu %s\n", ent->d_fileno,
ent->d_reclen, (unsigned short) ent->d_type,
(unsigned short) ent->d_namlen, ent->d_name);
}
/* test rewinddir */
printf("rewinding directory:\n");
rewinddir(dirp);
while ((ent = readdir(dirp)) != NULL) {
printf("\t%lu %hu %hu %hu %s\n", ent->d_fileno,
ent->d_reclen, (unsigned short) ent->d_type,
(unsigned short) ent->d_namlen, ent->d_name);
}
/* test closedir */
printf("closedir returns %d\n", closedir(dirp));
return 0;
}

56
lib/libc/tests/gen/err.c Normal file
View File

@ -0,0 +1,56 @@
/*
* Tests for gen/err.c
* Written by Devin Reade
*
* $Id: err.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void
custom_exit(int val) {
printf("in custom_exit with val %d\n", val);
exit(val);
}
int main(int argc, char **argv) {
int i;
if (argc != 2) {
printf("usage!\n");
exit(1);
}
printf("testing err_set_file\n");
err_set_file(stdout);
printf("testing err_set_exit\n");
err_set_exit(custom_exit);
errno = ENOMEM;
printf("testing warn and vwarn\n");
warn("\ttest of %s", "warn");
printf("testing warnx and vwarnx\n");
warnx("\ttest of warnx");
i = atoi(argv[1]);
switch (i) {
case 0:
printf("testing err and verr\n");
err(1, "\ttest of %s", "err");
break;
case 1:
printf("testing errx and verrx\n");
errx(2, "\ttest of %s", "verrx"); /* bogus */
break;
default:
printf("unknown case: %d\n", i);
exit(1);
}
return 0;
}

View File

@ -0,0 +1,25 @@
/*
* Test written by Devin Reade
*
* This one doesn't test the flags parameter yet.
*
* $Id: fnmatch.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <fnmatch.h>
#include <stdlib.h>
#include <stdio.h>
int
main (int argc, char **argv) {
int result;
if (argc != 3) {
printf("usage: %s pattern filename\n", argv[0]);
exit(1);
}
result = fnmatch (argv[1], argv[2], FNM_CASEFOLD);
printf("result is %d\n", result);
return 0;
}

View File

@ -0,0 +1,40 @@
#line 1 ":trenco4:gno.src:lib:libc:tests:gen:getcwd.c"
/*
* Test written by Devin Reade.
*
* $Id: getcwd.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#define BUFFERSIZE PATH_MAX
#define BUFFERSIZE2 15
__const char *__const sys_siglist[] = { "dummy list", NULL };
int main (int argc, char **argv) {
static char buffer[BUFFERSIZE];
static char buffer2[BUFFERSIZE2];
char *p, *buf;
int i, len;
for (i=0; i<3; i++) {
switch (i) {
case 0: buf = NULL; len = 0; break; /* should pass */
case 1: buf = buffer; len = BUFFERSIZE; break; /* should pass */
case 2: buf = buffer2; len = BUFFERSIZE2; break; /* should fail */
default: assert(0);
}
p = getcwd(buf, len);
if (p == NULL) {
perror("getcwd failed");
} else {
printf("cwd is \"%s\"\n", p);
}
}
return 0;
}

View File

@ -0,0 +1,64 @@
/*
* Test by Devin Reade.
*
* $Id: getgrent.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <sys/types.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WHEEL "wheel"
int main(int argc, char **argv) {
struct group *gp;
int id, i, j;
char **pp;
for (j=0; j<2; j++) {
switch (j) {
case 0:
printf("printing all entries\n");
break;
case 1:
printf("resetting file pointer\n");
setgrent();
break;
}
while((gp = getgrent()) != NULL) {
printf("entry: %s %s %d ", gp->gr_name,
gp->gr_passwd, gp->gr_gid);
pp = gp->gr_mem;
for (i=0; pp[i] != NULL; i++) {
printf ("%s ", pp[i]);
}
printf("\n");
}
}
if (argc > 1) {
if (!strcmp(argv[1], WHEEL)) {
if ((gp = getgrnam(argv[1])) == NULL) {
printf("%s not present in database\n",
argv[1]);
} else {
printf("group number for %s is %d\n",
argv[1], gp->gr_gid);
}
} else {
id = atoi(argv[1]);
if ((gp = getgrgid(id)) == NULL) {
printf("group %d not present in database\n",
id);
} else {
printf("group name for %d is %s\n",
id, gp->gr_name);
}
}
}
endgrent();
return 0;
}

View File

@ -0,0 +1,63 @@
/*
* Test by Devin Reade.
*
* $Id: getpwent.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#pragma debug 25
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WHOAMI "glyn"
int main(int argc, char **argv) {
struct passwd *pw;
int id, i, j;
char **pp;
for (j=0; j<2; j++) {
switch (j) {
case 0:
printf("printing all entries\n");
break;
case 1:
printf("resetting file pointer\n");
setpwent();
break;
}
while((pw = getpwent()) != NULL) {
printf("entry: \"%s\" \"%s\" %u %u\n",
pw->pw_name, pw->pw_passwd,
pw->pw_uid, pw->pw_gid);
}
}
if (argc > 1) {
if (!strcmp(argv[1], WHOAMI)) {
if ((pw = getpwnam(argv[1])) == NULL) {
printf("%s not present in database\n",
argv[1]);
} else {
printf("uid for %s is %u\n",
argv[1], pw->pw_uid);
}
} else {
id = atoi(argv[1]);
if ((pw = getpwuid(id)) == NULL) {
printf("uid %u not present in database\n",
id);
} else {
printf("id for %u is %s using shell %s\n",
id, pw->pw_name, pw->pw_shell ?
pw->pw_shell : "(null)");
}
}
}
endpwent();
return 0;
}

View File

@ -0,0 +1,51 @@
/*
* Test by Devin Reade
*
* $Id: popen.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#define BUFFERSIZE 1024
char buffer[BUFFERSIZE];
int main (int argc, char **argv) {
FILE *fp;
int errflag = 0;
int c;
char *mode;
while ((c = getopt(argc, argv, "rw")) != EOF) {
switch (c) {
case 'r':
mode = "r";
break;
case 'w':
mode = "w";
break;
default:
warnx("unknown option: %c", c);
errflag++;
}
}
if (errflag) {
exit(1);
}
if (argc - optind != 1) {
errx(1,"one argument required");
}
if ((fp = popen(argv[optind], mode)) == NULL) {
err(1, "popen failed");
}
while (fgets(buffer, BUFFERSIZE, fp) != NULL) {
printf("T: %s", buffer);
}
printf("now doing pclose\n");
c = pclose(fp);
printf("pclose returned %d\n", c);
return c;
}

View File

@ -0,0 +1,55 @@
/*
* Test by Devin Reade.
*
* $Id: scandir.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#define FAIL(arg) { fprintf(stderr,"%s (errno==%d)\n", arg, errno); exit(1); }
int main (int argc, char **argv) {
struct dirent **namelist;
char *path;
int count, i, loop;
if (argc != 2) {
printf("usage: %s dir_name\n", argv[0]);
exit(1);
}
path = argv[1];
for (loop = 0; loop < 2; loop++) {
switch(loop) {
case 0:
printf("sorting %s\n", path);
count = scandir(path, &namelist, NULL, alphasort);
break;
case 1:
printf("sorting %s (case insensitive)\n", path);
count = scandir(path, &namelist, NULL, alphacasesort);
break;
default:
assert(0);
}
if (count == -1) {
FAIL("scandir failed");
}
for (i=0; i<count; i++) {
printf("\t%s\n", namelist[i]->d_name);
}
printf("freeing pointers: ");
for (i=0; i<count; i++) {
printf(" %d", i);
free(namelist[i]);
}
printf("\n");
free(namelist);
}
return 0;
}

View File

@ -0,0 +1,26 @@
#pragma optimize -1
#include <setjmp.h>
#include <signal.h>
jmp_buf my_jump;
#pragma databank 1
void my_handler(int sig, int code)
{
printf("WHEEE!\n");
asm {brk 2}
longjmp(my_jump, 1);
}
#pragma databank 0
int main(int argc, char *argv[])
{
sigblock(sigmask(SIGPIPE)); /* something to make the mask interesting */
signal(SIGTSTP, my_handler);
asm {brk 0}
setjmp(my_jump);
asm {brk 1}
for (;;);
}

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <unistd.h>
#define DURATION 3
int main (int argc, char **argv) {
printf("sleeping for %d seconds\n", DURATION);
sleep(DURATION);
printf("now awake, starting pause\n");
pause();
return 0;
}

View File

@ -0,0 +1,39 @@
#line 1 ":trenco4:gno.src:lib:libc:gen:testit.c"
#pragma lint -1
#pragma keep "testit"
#include <stdio.h>
#ifdef __GNO__
#include <unistd.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
int main (int argc, char **argv) {
int fd1, fd2;
if (argc != 2) {
printf("usage!\n");
exit(1);
}
printf("trying first open\n");
fd1 = open(argv[1], O_RDONLY);
if (fd1 == -1) {
perror("open 1 failed\n");
exit (1);
}
printf("trying second open\n");
fd2 = open(argv[1], O_RDONLY);
if (fd2 == -1) {
perror("open 2 failed\n");
exit (1);
}
printf("done!\n");
close(fd1);
close(fd2);
return 0;
}

View File

@ -0,0 +1,31 @@
/*
* Test by Devin Reade
*
* $Id: utime.c,v 1.1 1997/02/28 05:12:52 gdr Exp $
*/
#include <sys/types.h>
#include <utime.h>
#include <stdio.h>
#include <err.h>
#include <time.h>
#include <gno/gno.h>
int main(int argc, char **argv) {
struct utimbuf utb;
if (argc != 2) {
errx(1, "usage: %s filename", __prognameGS());
}
if ((utb.actime = time(NULL)) == -1) {
err(1, "time failed! (shouldn't happen)");
}
utb.modtime = utb.actime;
if (utime(argv[1], &utb) == -1) {
err(1, "utime for %s failed", argv[1]);
}
printf("passed\n");
return 0;
}

View File

@ -0,0 +1,19 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:54 gdr Exp $
#
.INCLUDE: ../../const.mk
LIBC := ../../libc
LDLIBS = -l$(LIBC)
CFLAGS := -v -w -G25 $(STACK) $(DEFINES) $(INCLUDES)
TARGETS = gnomisc gsstring
OBJS = gnomisc.o gsstring.o
default: $(TARGETS)
.PRECIOUS: $(OBJS)
clobber clean:
$(RM) -f $(TARGETS) $(OBJS)

View File

@ -0,0 +1,37 @@
/*
* This file tests routines from gno/gnomisc.c and gno/stack.asm
* Written by Devin Reade
*
* $Id: gnomisc.c,v 1.1 1997/02/28 05:12:54 gdr Exp $
*/
#include <stdio.h>
#include <gno/gno.h>
/* early debugging */
#if 0
char *optarg, *suboptarg;
int optopt, optind, opterr, __mb_cur_max;
#endif
void cleanup (void) {
printf("stack usage: %d bytes\n", _endStackCheck());
}
int main (int argc, char **argv) {
char *p;
printf("starting stack check\n");
_beginStackCheck();
atexit(cleanup);
printf("checking for GNO\n");
if (needsgno() == 0) {
printf("GNO is NOT active\n");
} else {
printf("GNO is active\n");
}
p = __prognameGS();
printf("program name is %s\n", p);
return 0;
}

View File

@ -0,0 +1,79 @@
/*
* Tests by Devin Reade
*
* $Id: gsstring.c,v 1.1 1997/02/28 05:12:55 gdr Exp $
*
* This file is formatted for tab stops every 8 columns.
*/
#include <types.h>
#include <gno/gno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define FAIL() \
{ \
printf("test failed at line %d of %s\n", __LINE__, __FILE__); \
exit(EXIT_FAILURE); \
}
#if 1
#define NO_RESOURCE() { printf("resource failure\n"); exit(EXIT_FAILURE); }
#else
#define NO_RESOURCE() \
{ \
perror("resource failure"); \
exit(EXIT_FAILURE); \
}
#endif
const char *str1 = "this is a test string\n";
const char *str2 = "this is longer than the first\n";
int main(int argc, char **arv) {
GSStringPtr ptr1, ptr2;
ResultBufPtr ptr3, ptr4;
size_t len1, len2;
printf("testing GIinit\n");
len1 = strlen(str1);
if ((ptr1 = GIinit(len1, str1)) == NULL) NO_RESOURCE();
if (len1 != ptr1->length) FAIL();
if (ptr1->text[len1] != '\0') FAIL();
if (strcmp(str1, ptr1->text)) FAIL();
printf("testing GIchange\n");
len2 = strlen(str2);
if ((ptr2 = GIchange(ptr1, len2, NULL)) == NULL) NO_RESOURCE();
if (len2 != ptr2->length) FAIL();
if (ptr2->text[len2] != '\0') FAIL();
if (ptr2->text[0] != '\0') FAIL();
printf("testing GIfree\n");
GIfree(ptr2);
#define RESULT_LEN1 300
#define RESULT_LEN2 10
printf("testing GOinit\n");
if ((ptr3 = GOinit(RESULT_LEN1, str1)) == NULL) NO_RESOURCE();
if (ptr3->bufSize != RESULT_LEN1 + 2*sizeof(word)) FAIL();
if (ptr3->bufString.length != len1) FAIL();
if (ptr3->bufString.text[len1] != '\0') FAIL();
if (strcmp(ptr3->bufString.text, str1)) FAIL();
printf("testing GOchange\n");
if (RESULT_LEN2 >= len1) FAIL();
if ((ptr4 = GOchange(ptr3, RESULT_LEN2, NULL)) == NULL) FAIL();
if (ptr4->bufSize != RESULT_LEN2 + 2*sizeof(word)) FAIL();
if (ptr4->bufString.length != RESULT_LEN2) FAIL();
if (ptr4->bufString.text[RESULT_LEN2] != '\0') FAIL();
if (strncmp(ptr4->bufString.text, str1, RESULT_LEN2)) FAIL();
printf("testing GOfree\n");
GOfree(ptr4);
printf("\nPASSED\n");
return 0;
}

View File

@ -0,0 +1,31 @@
#
# Makefile for libc/tests/hdr.compile
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:55 gdr Exp $
#
.INCLUDE: ../../const.mk
#
# These should be tested with and without the following macros #defined:
# _ANSI_SOURCE
# _POSIX_SOURCE
# TEST_SGTTY
# KERNEL
# Currently, defining KERNEL makes no difference for the arpa, protocols,
# or rpc tests.
#
# We don't currently test:
# net.c -- non-BSD and unprototyped; insufficient info
# protocols.c -- unchanged from Derek's original, which
# matches the BSD version.
#
CFLAGS += -DKERNEL
OBJS = netinet.o machine.o rpc.o arpa.o gno.o sys.o base.o
default: $(OBJS)
clobber:
$(RM) -f $(OBJS)

View File

@ -0,0 +1,13 @@
/*
* $Id: arpa.c,v 1.1 1997/02/28 05:12:55 gdr Exp $
*/
#include "test.h"
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <arpa/telnet.h>
#include <arpa/tftp.h>
int i;

View File

@ -0,0 +1,66 @@
/*
* $Id: base.c,v 1.1 1997/02/28 05:12:55 gdr Exp $
*/
#include "test.h"
#include <sys/types.h>
/*
* This set has no #include dependancies in the base directory, so the
* order doesn't matter.
*/
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#ifndef KERNEL
#include <fts.h>
#endif
#include <glob.h>
#include <grp.h>
#include <limits.h>
#include <netdb.h>
#include <paths.h>
#include <pwd.h>
#include <regexp.h>
#include <setjmp.h>
/*
* we can't include both of these; they are mutually exclusive ways
* of handling ttys
*/
#ifdef TEST_SGTTY
#include <sgtty.h>
#else
#include <termios.h>
#endif
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <termcap.h>
#include <time.h>
#include <ttyent.h>
#include <types.h>
#include <unistd.h>
#include <utime.h>
/*
* This set has _some_ dependancies in the base directory, so watch
* the order.
*/
#include <curses.h>
#include <db.h>
#include <resolv.h>
#include <utmp.h>
/* a real mess ... */
#if 0
#include <appletalk.h>
#endif
int i;

View File

@ -0,0 +1,15 @@
/*
* $Id: gno.c,v 1.1 1997/02/28 05:12:55 gdr Exp $
*/
#include "test.h"
#include <gno/conf.h>
#include <gno/gno.h>
#include <gno/proc.h>
#include <gno/kvm.h>
#include <gno/sim.h>
/* haven't yet determined if it will be dropped */
#if 0
#include <gno/kerntool.h>
#endif

View File

@ -0,0 +1,18 @@
/*
* $Id: machine.c,v 1.1 1997/02/28 05:12:55 gdr Exp $
*/
#include "test.h"
#include <machine/types.h>
#include <machine/ansi.h>
#include <machine/endian.h>
#include <machine/limits.h>
#include <machine/param.h>
#include <machine/signal.h>
int i;

View File

@ -0,0 +1,23 @@
/*
* $Id: net.c,v 1.1 1997/02/28 05:12:55 gdr Exp $
*/
#include "test.h"
#include <net/af.h>
#include <net/dli_var.h>
#include <net/etherdefs.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/netbuf.h>
#include <net/netif.h>
#include <net/netisr.h>
#include <net/raw_cb.h>
#include <net/route.h>
int i;

View File

@ -0,0 +1,14 @@
/*
* $Id: netinet.c,v 1.1 1997/02/28 05:12:55 gdr Exp $
*/
#include "test.h"
#include <sys/types.h>
/* test begins */
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
int i;

View File

@ -0,0 +1,10 @@
/*
* $Id: protocols.c,v 1.1 1997/02/28 05:12:56 gdr Exp $
*/
#include "test.h"
/* this is probably missing a goodly number of prerequisites */
#include <protocols/talkd.h>
int i;

View File

@ -0,0 +1,9 @@
/*
* $Id: rpc.c,v 1.1 1997/02/28 05:12:56 gdr Exp $
*/
#include "test.h"
#include <rpc/types.h>
int i;

View File

@ -0,0 +1,44 @@
/*
* $Id: sys.c,v 1.1 1997/02/28 05:12:56 gdr Exp $
*/
#include "test.h"
/*
* This set has no #include dependancies in sys, so the order doesn't
* matter.
*/
#include <sys/cdefs.h>
#include <sys/dirent.h>
#include <sys/errno.h>
#include <sys/ioccom.h>
#include <sys/ttydefaults.h>
#include <sys/ttydev.h>
#include <sys/unistd.h>
#include <sys/syslimits.h>
/* This set has _some_ dependancies in sys, so watch the order. */
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/time.h>
#include <sys/mount.h>
#include <sys/ports.h>
#include <sys/select.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/times.h>
#include <sys/ttycom.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/ttychars.h>
#include <sys/ioctl_compat.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
#include <sys/tty.h>
#include <sys/param.h>
int i;

View File

@ -0,0 +1,19 @@
/*
* $Id: test.h,v 1.1 1997/02/28 05:12:56 gdr Exp $
*/
#ifdef KERNEL
#ifdef __STDC__
#define __P(a) a
#else
#define __P(a) ()
#endif
typedef void (*__SIG_FUNC__) __P((int, int));
#ifndef _POSIX_SOURCE
typedef __SIG_FUNC__ sig_t;
#endif
#endif /* KERNEL */

View File

@ -0,0 +1,13 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:56 gdr Exp $
#
.INCLUDE: ../../const.mk
LIBC := ../../libc
LDLIBS = -l$(LIBC)
CFLAGS := -v -w -G25 $(STACK) $(DEFINES) $(INCLUDES)
default: perror
.PRECIOUS: perror.o

View File

@ -0,0 +1,32 @@
/*
* Test by Devin Reade
*
* $Id: perror.c,v 1.1 1997/02/28 05:12:57 gdr Exp $
*/
#pragma debug 25
/* for now ... */
#define sys_nerr _gno_sys_nerr
#define sys_errlist _gno_sys_errlist
#include <stdio.h>
#include <errno.h>
int main (int argc, char **argv) {
int i;
fprintf(stderr, "ELAST is %d\n", ELAST);
if (argc > 1) {
for (i=0; i<sys_nerr; i++) {
fprintf(stderr, "loop %d\t\"%s\"\n", i, sys_errlist[i]);
}
} else {
for (i=0; i<sys_nerr; i++) {
fprintf(stderr, "loop %d\t", i);
errno = i;
perror("testing perror");
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:57 gdr Exp $
#
.INCLUDE: ../../const.mk
LIBC := ../../libc
LDLIBS = -l$(LIBC)
CFLAGS := -v -w -G25 $(STACK) $(DEFINES) $(INCLUDES)
default: environ
.PRECIOUS: environ.o

View File

@ -0,0 +1,431 @@
/*
* Tests implemented by Devin Reade
*
* $Id: environ.c,v 1.1 1997/02/28 05:12:57 gdr Exp $
*
* This file has been formatted with tab stops every 8 columns.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <types.h>
#include <shell.h>
#include <errno.h>
#define NONE_SET 0x00
#define UNIX_SET 0x01
#define ORCA_SET 0x02
#define BOTH_SET 0x03
extern char **environ;
static char *string1="testname";
static char *string2="testvalue";
static char *string3="testname=testvalue";
int use_environ;
/*
* void print_Unix_environ (void);
*
* Pre: none.
*
* Post: the environment residing in the environ structure is printed
* to stdout.
*/
void
print_Unix_environ (void) {
char **e, *s;
const char *fname = "print_Unix_environ";
if (!environ) {
printf("%s: environ is NULL\n", fname);
return;
}
e = environ;
if (*e==NULL) {
printf("%s: environment is empty\n", fname);
}
while (*e != NULL) {
s = *e;
if (*s == (char)NULL) {
printf("%s: entry of zero length\n", fname);
} else {
printf("%s\n",s);
}
e++;
}
return;
}
/*
* void print_Orca_environ (void);
*
* Pre: none.
*
* Post: the environment residing internal to the shell is printed to stderr.
* It's not terribly efficient, but then it doesn't have to be ;)
*/
void
print_Orca_environ (void) {
static ReadIndexedGSPB parmBuffer;
static ResultBuf255 nameBuffer, valueBuffer;
static char *fname = "print_Orca_environ";
char *entry;
unsigned int nameLength, valueLength;
/*
* initialize the parameter block
*/
parmBuffer.pCount = 4;
parmBuffer.index = 1;
nameBuffer.bufSize = sizeof (GSString255);
valueBuffer.bufSize = sizeof (GSString255);
parmBuffer.name = &nameBuffer;
parmBuffer.value = &valueBuffer;
/* loop until we've got them all */
ReadIndexedGS (&parmBuffer);
nameLength = nameBuffer.bufString.length;
while (nameLength != 0) {
valueLength = valueBuffer.bufString.length;
/* allocate the new environ entry */
entry = malloc (nameLength + valueLength + 2);
if (entry == NULL) {
printf("malloc failed in %s: %s\n", fname,
strerror(errno));
exit(1);
}
/* copy the name and value */
strncpy (entry, nameBuffer.bufString.text, nameLength);
entry[nameLength] = (char) NULL;
strcat (entry, "=");
strncat (entry, valueBuffer.bufString.text, valueLength);
entry[nameLength + valueLength + 1] = (char) NULL;
printf("%s\n",entry);
free(entry);
/* get the next shell variable and continue ... */
parmBuffer.index++;
ReadIndexedGS (&parmBuffer);
nameLength = nameBuffer.bufString.length;
}
return;
}
unsigned int
test_environ (void) {
unsigned int unix_set = 0;
unsigned int orca_set = 0;
char *s;
char **e;
/* test unix version */
if (use_environ) {
#ifdef DEBUG
printf("\n\nUnix environment:\n\n");
print_Unix_environ ();
printf("\n\n");
#endif
e = environ;
while (e && *e) {
if (strncmp(*e,string3,strlen(string3)) == 0) {
unix_set = UNIX_SET;
}
e++;
}
}
/* test Orca version */
if (getenv(string1) != NULL) {
orca_set = ORCA_SET;
}
return (unix_set | orca_set);
}
int
main (int argc, char **argv) {
int i=1; /* the number of the test */
unsigned int result;
if (argc > 1) {
use_environ = 1;
} else {
use_environ = 0;
printf("NOT ");
}
printf("using environ global variable\n");
/*
* initial Test 1:1
*/
result = test_environ();
if (result != NONE_SET) {
printf("Please unset the variable \"%s\" for this test.\n",
string1);
return -1;
}
printf("Test %d passed.\n",i);
i++;
#define FAIL(fmt) { printf(fmt, i, string1); exit(1); }
/*
* environInit(); Test :2
*/
if (use_environ) {
environInit();
result = test_environ();
switch (result) {
case BOTH_SET: FAIL("Test %d failed. %s prematurely set\n");
case ORCA_SET: FAIL("Test %d failed. %s set internally\n");
case UNIX_SET: FAIL("Test %d failed. %s set in environ\n");
case NONE_SET:
printf("Test %d passed.\n",i);
i++;
break;
default:
printf("Test internal error: test %d returned %ud\n",
i, result);
return -1;
}
}
/*
* setenv(); Test 2:3
*/
if (setenv(string1,string2,1) != 0) {
printf("Test %d: setenv() failed\n",i);
return -1;
}
result = test_environ();
if (use_environ) {
switch (result) {
case BOTH_SET:
printf("Test %d passed.\n",i);
i++;
break;
case ORCA_SET:
FAIL("Test %d failed. %s not set in environ\n");
case UNIX_SET:
FAIL("Test %d failed. %s not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
printf("Test internal error: test %d returned %ud\n",
i, result);
return -1;
}
} else {
switch (result) {
case BOTH_SET:
FAIL("Test %d failed. %s set in environ\n");
case ORCA_SET:
printf("Test %d passed.\n", i);
i++;
break;
case UNIX_SET:
FAIL("Test %d failed. %s set in environ, not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
printf("Test internal error: test %d returned %ud\n",
i, result);
return -1;
}
}
/*
* unsetenv() Test 3:4
*/
unsetenv(string1);
result = test_environ();
if (use_environ) {
switch (result) {
case BOTH_SET:
FAIL("Test %d failed. %s set\n");
case ORCA_SET:
FAIL("Test %d failed. %s set internally\n");
case UNIX_SET:
FAIL("Test %d failed. %s set in in environ\n");
case NONE_SET:
printf("Test %d passed.\n",i);
i++;
break;
default:
printf("Test internal error: test %d returned %ud\n",
i, result);
return -1;
}
} else {
switch (result) {
case BOTH_SET:
FAIL("Test %d failed. %s set\n");
case ORCA_SET:
FAIL("Test %d failed. %s set internally\n");
case UNIX_SET:
FAIL("Test %d failed. %s set in environ\n");
case NONE_SET:
printf("Test %d passed.\n",i);
i++;
break;
default:
printf("Test internal error: test %d returned %ud\n",
i, result);
return -1;
}
}
/*
* environPush() Test 4:5 bork
*/
if (setenv(string1,string2,1) != 0) {
printf("Test %d: setenv() failed\n",i);
return -1;
}
if (environPush() != 0) {
printf("Test %d: environPush() failed\n",i);
return -1;
}
result = test_environ();
if (use_environ) {
switch (result) {
case BOTH_SET:
printf("Test %d passed.\n",i);
i++;
break;
case ORCA_SET:
FAIL("Test %d failed. %s not set in environ\n");
case UNIX_SET:
FAIL("Test %d failed. %s not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
assert(0);
}
} else {
switch (result) {
case BOTH_SET:
FAIL("Test %d failed. %s set in environ\n");
case ORCA_SET:
printf("Test %d passed.\n",i);
i++;
break;
case UNIX_SET:
FAIL("Test %d failed. %s set in environ, not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
assert(0);
}
}
/*
* environPop() Test 5:6
*/
unsetenv(string1);
environPop();
result = test_environ();
if (use_environ) {
switch (result) {
case BOTH_SET:
printf("Test %d passed.\n",i);
i++;
break;
case ORCA_SET:
FAIL("Test %d failed. %s not set in environ\n");
case UNIX_SET:
FAIL("Test %d failed. %s not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
assert(0);
}
} else {
switch (result) {
case BOTH_SET:
FAIL("Test %d failed. %s set in environ\n");
case ORCA_SET:
printf("Test %d passed.\n",i);
i++;
break;
case UNIX_SET:
FAIL("Test %d failed. %s set in environ, not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
assert(0);
}
}
/*
* putenv() Test 6:7
*/
unsetenv(string1);
if (putenv(string3) != 0) {
printf("Test %d: putenv() failed\n",i);
return -1;
}
result = test_environ();
if (use_environ) {
switch (result) {
case BOTH_SET:
printf("Test %d passed.\n",i);
i++;
break;
case ORCA_SET:
FAIL("Test %d failed. %s not set in environ\n");
case UNIX_SET:
FAIL("Test %d failed. %s not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
assert(0);
}
} else {
switch (result) {
case BOTH_SET:
FAIL("Test %d failed. %s set in environ\n");
case ORCA_SET:
printf("Test %d passed.\n",i);
i++;
break;
case UNIX_SET:
FAIL("Test %d failed. %s set in environ, not set internally\n");
case NONE_SET:
FAIL("Test %d failed. %s not set\n");
default:
assert(0);
}
}
unsetenv(string1);
printf("Tests done.\n");
return 0;
}

View File

@ -0,0 +1,15 @@
#
# $Id: Makefile,v 1.1 1997/02/28 05:12:57 gdr Exp $
#
.INCLUDE: ../../../const.mk
LDLIBS = -l ../../libc
CFLAGS := -v -w -G25 $(STACK) $(DEFINES) $(INCLUDES)
default: creat exectest stat.o trap1
.PRECIOUS: creat.o exectest.o stat.o trap1.o
.INCLUDE: ../../rules.mk

View File

@ -0,0 +1,37 @@
/*
* $Id: creat.c,v 1.1 1997/02/28 05:12:57 gdr Exp $
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define FILE1 "data/creat1"
#define FILE2 "data/creat2"
int
main(int argc, char **argv) {
int i;
if ((i = creat(FILE1, 0644)) == -1) {
printf("mode 0644 failed: %d\n", errno);
exit(1);
} else {
close(i);
}
if ((i = creat(FILE2, 0444)) == -1) {
printf("mode 0444 failed: %d\n", errno);
unlink(FILE1);
exit(1);
} else {
close(i);
}
unlink(FILE1);
unlink(FILE2);
return 0;
}

View File

@ -0,0 +1,80 @@
/*
* Test for exec* routines written by Devin Reade
*
* $Id: exectest.c,v 1.1 1997/02/28 05:12:57 gdr Exp $
*
* This file is formatted for tab stops every 8 characters.
*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#pragma debug 0
char *argarray[4];
char *envarray[2]; /* for execve test */
char *envstring="bork=thingamadoo";
char *filestr1="now2";
int
main (int argc, char **argv) {
int i;
if (argc!=5) {
printf("usage: exectest case prog opt1 opt2\n");
printf("\tcase is one of:\n");
printf("\t\t0 - execl\n");
printf("\t\t1 - execlp\n");
printf("\t\t2 - execve\n");
printf("\t\t3 - execv\n");
printf("\t\t4 - execvp\n");
exit (-1);
}
i = atoi(argv[1]);
switch (i) {
case 0:
execl(argv[2], argv[2], argv[3], argv[4], (char *) NULL);
perror("execl() failed");
break;
case 1:
execlp(argv[2], argv[2], argv[3], argv[4], (char *) NULL);
perror("execlp() failed");
break;
case 2:
envarray[0]=envstring;
envarray[1]=NULL;
argarray[0]=argv[2];
argarray[1]=argv[3];
argarray[2]=argv[4];
argarray[3]=NULL;
execve(argarray[0], argarray, envarray);
perror("execve failed");
break;
case 3:
argarray[0]=argv[2];
argarray[1]=argv[3];
argarray[2]=argv[4];
argarray[3]=NULL;
execv(argarray[0], argarray);
perror("execv failed");
break;
case 4:
argarray[0]=argv[2];
argarray[1]=argv[3];
argarray[2]=argv[4];
argarray[3]=NULL;
execvp(argarray[0], argarray);
perror("execvp failed");
break;
default:
printf("bad case value: %d\n", i);
}
return -1;
}

34
lib/libc/tests/sys/stat.c Normal file
View File

@ -0,0 +1,34 @@
/*
* Test by Devin Reade
*
* $Id: stat.c,v 1.1 1997/02/28 05:12:58 gdr Exp $
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#define FAIL(msg) {printf("%s\n", msg); exit(1); }
int main(int argc, char **argv) {
struct stat sb;
char *path;
if (argc != 2) {
printf("usage: %s filename\n", argv[0]);
exit(1);
}
path = argv[1];
if (stat (path, &sb) == -1) {
FAIL("stat failed");
}
printf("file\t= %s\n", path);
printf("device\t= %#4x\n", sb.st_dev);
printf("mode\t= %#4x\n", sb.st_mode);
return 0;
}

View File

@ -0,0 +1,46 @@
#line 1 ":trenco4:custom.src:contrib:libc:tests:sys:trap1.c"
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gno/gno.h>
#define FAIL() { printf("TEST FAILED\n"); exit (1); }
#define PASS() { printf("test passed\n"); exit (0); }
#define VERSION_TRIPLE(val) \
(((val)&0xFF00) >> 8), \
(((val)&0x00F0) >> 4), \
(((val)&0x000F) >> 0)
extern int _toolErr;
int main (int argc, char **argv) {
u_short kernelVersion;
kernStatus();
if (_toolErr) {
printf("kernStatus returned %d\n", _toolErr);
FAIL();
}
kernelVersion = kernVersion();
if (_toolErr) {
printf("kernVersion failed with code %d\n", _toolErr);
FAIL();
} else if (kernelVersion < 0x0204) {
printf("there are no tests for kernel version %d.%d.%d\n",
VERSION_TRIPLE(0x0204));
} else {
printf("running tests for kernel version %d.%d.%d\n",
VERSION_TRIPLE(0x0204));
}
printf("SYSTEM CALL\t\t\tRETURN VALUE\n");
printf("getpid\t\t\t\t%d\n", getpid());
printf("setdebug(%d)\t\t\t%d\n", dbgSYSCALL, setdebug(dbgSYSCALL));
printf("setdebug(%d)\t\t\t%d\n", 0, setdebug(0));
return 0;
}