Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/old/lib/open.c
There are 10 other files named open.c in the archive. Click here to see a list.
/* <KCC.LIB>OPEN.C.19, 28-Aug-85 20:44:24, Edit by WHP4 */
/* copy ;P if handling file protection/mode in _cfile */
/* CREAT and OPEN are combined as they share a lot of code.
* This is also where the necessary data structures for I/O defined
* by URTIO.H are actually allocated.
*/
/* -------------------------------- */
/* create file */
/* ignore protection mode */
/* -------------------------------- */
/* ------------------- */
/* open file */
/* ------------------- */
#include <c-env.h>
#include <urtio.h>
/* Allocate the stuff */
int _uioch[UIO_MAXFILE];
#if SYS_WAITS
struct bufhead _buffers[UIO_MAXFILE]; /* file I/O buffers */
int _uioeof; /* end of file reached on terminal */
#endif
#define NULL 0
creat(name,mode)
char *name;
{
return _cfile(name,mode,7,0);
}
bcreat(name,mode)
char *name;
{
return _cfile(name,mode,8,0);
}
icreat(name,mode)
char *name;
{
return _cfile(name,mode,36,0);
}
#if SYS_T20+SYS_10X
#define GJOLD 0100000000000 /* get JFN for existing file */
#define OFAP 0020000 /* open file with append access */
#define OFWR 0100000 /* open file with write access */
#define OFRD 0200000 /* open file with read access */
/* ----------------------------------- */
/* handler for file creation */
/* ----------------------------------- */
_cfile(name,mode,omode,app)
char *name;
{
int channel, f;
char nbuf[100], *s; /* make name buffer */
if (mode > 0) {
s = nbuf;
while (*s++ = *name++) ; /* copy name part of string */
name = ";P"; /* plus protection attrib */
s--;
while (*s++ = *name++) ; /* copy the protection attrib too */
s--;
f = modprot(mode >> 6); /* user prots */
*s++ = (f >> 3) + '0';
*s++ = (f & 7) + '0';
f = modprot(mode >> 3); /* group prots */
*s++ = (f >> 3) + '0';
*s++ = (f & 7) + '0';
f = modprot(mode); /* other prots */
*s++ = (f >> 3) + '0';
*s++ = (f & 7) + '0';
s = nbuf; /* point to start again */
} else s = name;
f = app ? 0 : 0777777;
channel = _gtjfn(s, f); /* get JFN */
if (channel < 0) return -1; /* make sure got one */
f = OFRD | OFWR;
if (app)
f |= OFAP;
if (_openf(channel, f, omode) <= 0) return -1;
if (f = _uiofd()) { /* get descriptor for it */
_uioch[f] = channel; /* set JFN in descriptor */
return f; /* return with it */
}
return -1; /* no fds avail, fail */
}
/* ------------------------------------ */
/* file protection conversion */
/* ------------------------------------ */
static modprot(mod)
{
int prot;
prot = 0;
if (mod & 1) prot |= 012; /* execute (and list) access */
if (mod & 2) prot |= 027; /* write and append access */
if (mod & 4) prot |= 042; /* read (and list) access */
return prot;
}
#endif /* T20+10X */
#if SYS_WAITS
/* ----------------------------------- */
/* handler for file creation */
/* ----------------------------------- */
static _cfile(name,mode,omode)
char *name;
{
int channel,f,buf,device,disk;
struct filespec fs;
if (*name == ':') {
name++;
device = sixbit(name);
disk = 0;
}
else {
disk = device = sixbit("DSK");
}
if (convert(name,&fs) && (f = _uiofd())) {
buf = getbuf(f);
switch (omode) {
case 7:
if (_open(f,buf<<18,device)) break;
return -1;
case 8:
if (_bopen(f,buf<<18,device)) break;
return -1;
case 36:
if (_iopen(f,buf<<18,device)) break;
return -1;
}
if (disk) {
if (!_enter(f,&fs)) return -1;
}
_out(f);
return _uioch[f] = f;
}
return -1;
}
#endif /* WAITS */
#if SYS_ITS
_cfile(name, umode, bsize, appflg)
char *name;
int umode,bsize,appflg;
{
return(_ofile(name, 1, bsize));
}
#endif /* ITS */
open(name,mode) /* 7-bit ASCII files */
char *name;
{
return _ofile(name,mode,7);
}
bopen(name,mode) /* 8-bit byte open */
char *name;
{
return _ofile(name,mode,8);
}
iopen(name,mode) /* 36-bit byte open */
char *name;
{
return _ofile(name,mode,36);
}
#if SYS_T20+SYS_10X
/* ------------------------------- */
/* handler for file open */
/* ------------------------------- */
_ofile(name,mode,omode)
char *name;
{
int channel, f;
if ((mode = getmode(mode)) == -1) return -1; /* convert OPENF bits */
channel = _gtjfn(name, GJOLD); /* get JFN */
if (channel < 0) return -1; /* make sure got one */
if (!_openf(channel, mode, omode)) return -1;
if (f = _uiofd()) { /* get descriptor for it */
_uioch[f] = channel; /* set JFN in descriptor */
return f; /* return with it */
}
return -1; /* no fds avail, fail */
}
/* ------------------------------------------------- */
/* convert UNIX to TOPS-20 file open modes */
/* ------------------------------------------------- */
static getmode(n)
{
switch (n) {
case O_RDONLY:
return OFRD;
case O_WRONLY:
return OFWR;
case O_RDWR:
return OFRD|OFWR;
default:
return -1;
}
}
/* --------------------------------------------------------------------- */
/* jacket routine for GTJFN% to mung filenames into submission */
/* --------------------------------------------------------------------- */
int _gtjfn(name, flags)
char *name;
{
char dirpart[80], filpart[80], *dirptr, *filptr, *_dirst();
int anydir, indir; /* marker for dir part changed */
anydir = 0; /* dir part remains default */
indir = 0; /* assume not in directory part */
dirpart[0] = 'D'; /* start off with directory part */
dirpart[1] = 'S'; /* pointing to "DSK:" */
dirpart[2] = 'K';
dirpart[3] = ':';
dirptr = &dirpart[3]; /* point to just before the end */
filptr = &filpart[-1]; /* of dir and file parts */
while (1) {
switch (*name) {
case '\0': /* run out of chars? */
*++filptr = 0; /* yes, null terminate */
filptr = &filpart[-1]; /* start at top again */
while (*++dirptr = *++filptr) ; /* append to dir part */
return gtjfn_(dirpart, flags); /* do low level lookup */
case ':':
if (anydir) return -1; /* already have dir, lose */
anydir = 1; /* now we have one */
*++filptr = '\0'; /* terminate file part */
dirptr = &dirpart[-1]; /* start at top */
filptr = &filpart[-1]; /* top of filename part */
while (*++dirptr = *++filptr); /* copy across */
*dirptr = ':'; /* put the colon on */
filptr = &filpart[-1]; /* reinitialize file pointer */
break;
case '[':
case '<':
*++filptr = '<'; /* open bracket becomes angle */
indir = 1; /* remember we're in dir part */
break;
case '.':
if (indir < 0) *++filptr = '\026'; /* quote extra dots */
else if (indir == 0) indir = -1; /* only allow one in file */
*++filptr = '.'; /* add the dot */
break;
case '>':
case ']':
if (*dirptr != ':') return -1; /* already have dir, lose */
anydir = 1; /* remember we have a dir and dev */
indir = 0; /* no longer in dir part */
*++filptr = '\0'; /* terminate file part */
filptr = &filpart[-1]; /* top of filename part */
while (*++dirptr = *++filptr); /* copy across */
*dirptr = '>'; /* add the close bracket */
filptr = &filpart[-1]; /* reinitialize file pointer */
break;
case '\026': /* control-V? */
case '\\': /* or quoteing backslash? */
*++filptr = '\026'; /* yes, add it */
*++filptr = *++name; /* and the next char */
break;
case '/': /* slash UNIX dir delimiter? */
indir = 0; /* yes, no longer in dir part */
*(dirptr+1) = '\0'; /* yes, terminate directory part */
*++filptr = '\0'; /* and filename part */
switch (filpart[0]) { /* check out first part of name */
case '.': /* period? */
switch (filpart[1]) { /* yes, look at what follows */
case '\0': /* ./x ? */
name++; /* yes, skip slash */
filptr = &filpart[-1]; /* start again in file part */
continue; /* and ignore this dir part */
default:
return -1; /* .x/y loses */
case '\026': /* maybe ..? */
break; /* yes, handle outside switch */
}
/* dir starts with .. - hack superdirectory */
if (filpart[2] != '.' || filpart[3] != '\0') return -1;
if (*dirptr != '>') { /* do we have a real dir part? */
dirptr = _dirst(dirpart); /* no, fix it up */
if (dirptr == NULL) return -1; /* lost */
}
while (*--dirptr != '.' && *dirptr != ':') ; /* find delim */
if (*dirptr == '.') { /* found subdir start? */
*dirptr = '>'; /* turn into dir end */
name++; /* skip over slash */
filptr = &filpart[-1]; /* forget .. */
continue; /* on with the show */
}
/* no subdirs, move back to dev:<root-dir> */
case '\0': /* no name, want root dir */
if (*dirptr != ':') return -1; /* must have only dev */
filptr = "<ROOT-DIRECTORY" - 1; /* point to dir part */
break;
default:
if (*dirptr != '>') {
dirptr = _dirst(dirpart); /* fix up filename */
if (dirptr == NULL) return -1; /* lost */
}
*dirptr = '.'; /* drop period over close bracket */
filptr = &filpart[-1]; /* normal name, just use it */
}
while (*++dirptr = *++filptr) ; /* append name */
*dirptr = '>'; /* and close bracket */
filptr = &filpart[-1]; /* restart file part */
break;
default:
*++filptr = *name; /* normal char, add to file part */
break;
}
name++; /* move on to next char */
}
}
static int _openf();
#asm
; *************************************************************
; open file, return success or failure in AC1
; argument 1: JFN of file
; 2: byte size of open
; 3: mode word (OF%RD, OF%WR, etc)
; *************************************************************
SEARCH MONSYM
.OPENF: MOVE 1,-1(17) ;Get the JFN
MOVE 2,-3(17) ;Get byte size
LSH 2,^D30 ; shifted into position
IOR 2,-2(17) ;Include access bits
OPENF% ;Do the open
ERJMPA $RETF ; lost
JRST $RETT ; won
#endasm
static int gtjfn_();
#asm
; And here to get JFN from hacked filename
gtjfn.: MOVE 1,-2(17) ;Get flags.
TDO 1,[GJ%SHT] ;Make sure we want short form
%CHRBP 2,-1(17) ;Point to file name
GTJFN% ;Try getting the JFN
ERJMPA $RETN ;Error, return -1
POPJ 17, ;Success, return the JFN
#endasm
static char *_dirst();
#asm
; *************************************************************
; Get channel (JFN), return in AC1
; *************************************************************
; Here to canonicalize dir name
; Not sure if this is really needed for anything on TENEX.
.dirst:
#if SYS_T20
MOVE 1,[RC%EMO] ;Forcing exact match
%CHRBP 2,-1(17) ;From string pointer given as arg
RCDIR% ;Get directory number in AC3
ERJMP $RETF
TDNE 1,[RC%NOM] ;Matched?
JRST $RETF ;No, fail
%CHRBP 1,-1(17) ;From string
MOVE 2,3 ;With directory number
DIRST% ;Make string for dir number
ERJMP $RETF
#endif /* T20 */
#if SYS_10X
SETZ 1, ; Force exact match
%CHRBP 2,-1(17) ; for string pointer given as arg
STDIR% ; Get directory number in AC1(RH)
ERJMPA $RETF ; No match
ERJMPA $RETF ; Ambiguous
HRRZ 2,1 ; Set up dir number
%CHRBP 1,-1(17) ; Output to this string
DIRST% ; Make string for dir number
ERJMPA $RETF
#endif /* 10X */
POPJ 17, ;Did it, return with updated pointer
#endasm
#endif /* T20+10X */
#if SYS_WAITS
/* ------------------------------- */
/* handler for file open */
/* ------------------------------- */
static _ofile(name,mode,omode)
char *name;
{
int channel,f,buf,device,disk;
struct filespec fs;
if (*name == ':') {
name++;
device = sixbit(name);
disk = 0;
}
else {
disk = device = sixbit("DSK");
}
if (convert(name,&fs) && (f = _uiofd())) {
buf = getbuf(f);
switch (omode) {
case 7:
if (_open(f,buf,device)) break;
return -1;
case 8:
if (_bopen(f,buf,device)) break;
return -1;
case 36:
if (_iopen(f,buf,device)) break;
return -1;
}
if (disk) {
if (!_lookup(f,&fs)) return -1;
_in(f);
}
return _uioch[f] = f;
}
return -1;
}
/* --------------------------------------------------- */
/* obtain a sixbit representation for string */
/* --------------------------------------------------- */
static sixbit(s)
char *s;
{
int n,w,t;
w = 0;
n = 30;
while (*s && n >= 0) {
t = *s++;
if (t & 0100) t = t | 040; else t = t & 0137;
w += (t&077) << n;
n -= 6;
}
return w;
}
/* ----------------------------------------------------------------------- */
/* convert a filename string to internal filespec representation */
/* ----------------------------------------------------------------------- */
static convert(s,t)
char *s; struct filespec *t;
{
char u[16],*v;
int state;
state = 1;
t->name = t->extension = t->date = t->PPN = 0;
while (state) {
v = u;
while (!fend(*s)) *v++ = *s++;
*v = 0;
switch (state) {
case 1:
t->name = sixbit(u);
switch (*s) {
case 0:
state = 0;
break;
case '.':
state = 2;
break;
case '[':
state = 3;
break;
default:
return 0;
}
s++;
break;
case 2:
t->extension = sixbit(u) & 0777777000000;
switch (*s) {
case 0:
state = 0;
break;
case '[':
state = 3;
break;
default:
return 0;
}
s++;
break;
case 3:
t->PPN = rightjust(sixbit(u));
switch (*s) {
case ',':
state = 4;
break;
default:
return 0;
}
s++;
break;
case 4:
t->PPN += (rightjust(sixbit(u)) >> 18);
state = 0;
break;
default:
return 0;
}
}
return 1;
}
static fend(c)
{
if (c == 0 || c == '.' || c == '[' || c == ',' || c == ']') return 1;
return 0;
}
static rightjust(n)
{
if (n = n & 0777777000000) while (!(n & 077000000)) n = n >> 6;
return n;
}
/* -------------------------------------------------------- */
/* create an integer that contains buffer address */
/* -------------------------------------------------------- */
static getbuf(f)
{
return &buffers[f];
}
static _open(); _iopen(); _bopen(), _lookup(), _enter();
#asm
; ************************************************************
; initialize channel (chan #, bufptr, device)
; device is a sixbit /DSK/ or /TTY##/
; ************************************************************
;
.OPEN: MOVE 1,-1(17)
ANDI 1,17
LSH 1,27 ; shift channel # into ac field
MOVEI 2,0 ; 7 bit ascii mode
MOVE 3,-3(17) ; device usually sixbit /DSK/
MOVE 4,-2(17)
IOR 1,[OPEN 0,2]
MOVEM 1,.+1
OPEN 0,0
JRST $RETF ; error
JRST $RETT ; no error
; ************************************************************
; initialize image mode channel (chan #, bufptr,device)
; ************************************************************
;
.IOPEN:
.BOPEN: MOVE 1,-1(17)
ANDI 1,17
LSH 1,27 ; shift channel # into ac field
MOVEI 2,10 ; 36 bit image mode
MOVE 3,-3(17)
MOVE 4,-2(17)
IOR 1,[OPEN 0,2]
MOVEM 1,.+1
OPEN 0,0
JRST $RETF ; error
JRST $RETT ; no error
; ************************************************************
; open input file (chan #, bufptr)
; ************************************************************
;
.LOOKUP:MOVE 1,-1(17)
ANDI 1,17
LSH 1,27 ; shift channel # into ac field
IOR 1,[LOOKUP 0,0] ; assemble an ENTER UUO
HRR 1,-2(17)
MOVEM 1,.+1
LOOKUP 0,0
JRST $RETF ; error
JRST $RETT ; no error
; ************************************************************
; open output file (chan #, bufptr)
; ************************************************************
;
.ENTER: MOVE 1,-1(17)
ANDI 1,17
LSH 1,27 ; shift channel # into ac field
IOR 1,[ENTER 0,0] ; assemble an ENTER UUO
HRR 1,-2(17)
MOVEM 1,.+1
ENTER 0,0
JRST $RETF ; error
JRST $RETT ; no error
#endasm
#endif /* WAITS */
#if SYS_ITS
#include "sysits.h"
_ofile(name, umode, bsize)
char *name;
int umode,bsize;
{ int fd, res, modchn;
char *bp;
if((fd = _uiofd()) <= 0)
return(-1); /* No FDs available */
if((modchn = getchn()) < 0)
return(-1); /* No ITS chans available */
switch(umode)
{ case 0: /* Read */
break; /* Leave LH zero (.UAI) */
case 1: /* Write */
modchn |= (1<<18); /* Set .UAO */
break;
case 2: /* Reading and Writing */
return(-1); /* Sorry, don't support this */
}
--name; /* Back up ptr to make proper BP */
res = SYSCAL2(SC_NAM(sopen),SC_ARG(&modchn),SC_ARG(&name));
if(res) return(-1); /* Error of some kind */
_uioch[fd] = modchn&017;
return(fd);
}
#endif /* ITS */
/* ---------------------------------------- */
/* find an unused file descriptor */
/* ---------------------------------------- */
_uiofd()
{
int n;
n = 3;
while (n < UIO_MAXFILE && _uioch[n] != UIO_UNASS) n++;
return (n < UIO_MAXFILE) ? n : 0;
}