1305 lines
37 KiB
C
1305 lines
37 KiB
C
/* OS- and machine-dependent stuff for OSK machines
|
|
* Written by Bob, Brose, N0QBJ, 974 Hampden Ave, St Paul MN 55114-1108
|
|
*
|
|
|
|
Version Log
|
|
-----------
|
|
012093 - First OSK release.
|
|
022493 - Fixed bug in smtp, wasn't doing cr/lf correctly and SOME nos hosts
|
|
objected.
|
|
Fixed various FTP bugs (also caused by cr/lf conversions.
|
|
Fixed problem in ftpserver ls command response which should now
|
|
allow mgets from a remote host to work correctly (directory
|
|
access routines in this file altered).
|
|
081293 - Fixed bug in rename which was causing an abort on mailbox reads.
|
|
081693 - Fixed memory allocation bugs, space used by make_path was not
|
|
being freed.
|
|
Added the code for getcwd and cd.
|
|
|
|
*/
|
|
|
|
#include "global.h"
|
|
#include <time.h>
|
|
#include <stdio.h>
|
|
#include <sgstat.h>
|
|
#include <modes.h>
|
|
#include <dir.h>
|
|
#include <strings.h>
|
|
|
|
#include "osk.h"
|
|
#include "mbuf.h"
|
|
#include "internet.h"
|
|
#include "iface.h"
|
|
#include "cmdparse.h"
|
|
|
|
|
|
#define MAXCMD 80
|
|
unsigned nasy;
|
|
int IORser[ASY_MAX];
|
|
struct sgbuf orgsgbufi, orgsgbufo;
|
|
|
|
#ifndef _UCC
|
|
#define MAXTMP 26
|
|
struct FILREC {
|
|
FILE *filptr;
|
|
char tmpnam[32];
|
|
};
|
|
|
|
struct FILREC tmpfils[MAXTMP];
|
|
|
|
#endif
|
|
|
|
restore()
|
|
{
|
|
}
|
|
|
|
disable()
|
|
{
|
|
}
|
|
|
|
kbread()
|
|
{
|
|
unsigned char c;
|
|
|
|
if (getstat(1,0) < 0)
|
|
return -1;
|
|
|
|
read(0, &c, 1);
|
|
return c;
|
|
}
|
|
|
|
|
|
struct asy asy[ASY_MAX];
|
|
|
|
/* Interface list header */
|
|
struct interface *ifaces = NULL;
|
|
|
|
|
|
/* Called at startup time to set up console I/O, memory heap */
|
|
ioinit()
|
|
{
|
|
char termname[40];
|
|
struct sgbuf sbuf;
|
|
int i;
|
|
|
|
/* tmp file tracking array init, non-ucc */
|
|
|
|
#ifndef _UCC
|
|
for (i=0;i<MAXTMP;i++)
|
|
tmpfils[i].filptr=NULL;
|
|
#endif
|
|
_gs_devn(2, termname+1);
|
|
termname[0] = '/';
|
|
|
|
#ifdef STRANGECONS
|
|
fclose(stdin);
|
|
if (fopen(termname, "r+") != stdin)
|
|
exit(1000);
|
|
|
|
fclose(stdout);
|
|
if (fopen(termname, "w+") != stdout)
|
|
exit(2000);
|
|
|
|
if (fileno(stdin) != 0)
|
|
exit(3000);
|
|
|
|
if (fileno(stdout) != 1)
|
|
exit(4000);
|
|
#endif
|
|
|
|
_gs_opt(0,&sbuf);
|
|
memcpy(&orgsgbufi,&sbuf,sizeof(sbuf));
|
|
sbuf.sg_case = 0;
|
|
sbuf.sg_backsp = 0;
|
|
sbuf.sg_delete = 0;
|
|
sbuf.sg_echo = 0;
|
|
sbuf.sg_alf = 1;
|
|
sbuf.sg_nulls = 0;
|
|
sbuf.sg_pause = 0;
|
|
sbuf.sg_page = 0;
|
|
sbuf.sg_bspch = 0;
|
|
sbuf.sg_dlnch = 0;
|
|
sbuf.sg_eorch = 0;
|
|
sbuf.sg_eofch = 0;
|
|
sbuf.sg_rlnch = 0;
|
|
sbuf.sg_dulnch = 0;
|
|
sbuf.sg_psch = 0;
|
|
sbuf.sg_bsech = 0;
|
|
sbuf.sg_bellch = 0;
|
|
sbuf.sg_xon = 0;
|
|
sbuf.sg_xoff = 0;
|
|
sbuf.sg_tabcr = 0;
|
|
sbuf.sg_tabsiz = 0;
|
|
sbuf.sg_kbich = 0;
|
|
sbuf.sg_kbach = 0;
|
|
_ss_opt(0,&sbuf);
|
|
|
|
#ifdef STRANGECONS
|
|
_gs_opt(1,&sbuf);
|
|
memcpy(&orgsgbufo,&sbuf,sizeof(sbuf));
|
|
sbuf.sg_case = 0;
|
|
sbuf.sg_backsp = 0;
|
|
sbuf.sg_delete = 0;
|
|
sbuf.sg_echo = 0;
|
|
sbuf.sg_alf = 1;
|
|
sbuf.sg_nulls = 0;
|
|
sbuf.sg_pause = 0;
|
|
sbuf.sg_page = 0;
|
|
sbuf.sg_bspch = 0;
|
|
sbuf.sg_dlnch = 0;
|
|
sbuf.sg_eorch = 0;
|
|
sbuf.sg_eofch = 0;
|
|
sbuf.sg_rlnch = 0;
|
|
sbuf.sg_dulnch = 0;
|
|
sbuf.sg_psch = 0;
|
|
sbuf.sg_bsech = 0;
|
|
sbuf.sg_bellch = 0;
|
|
sbuf.sg_xon = 0;
|
|
sbuf.sg_xoff = 0;
|
|
sbuf.sg_tabcr = 0;
|
|
sbuf.sg_tabsiz = 0;
|
|
sbuf.sg_kbich = 0;
|
|
sbuf.sg_kbach = 0;
|
|
_ss_opt(1,&sbuf);
|
|
#endif
|
|
|
|
setbuf(stdin,NULL);
|
|
}
|
|
|
|
/* Called just before exiting to restore console state */
|
|
iostop()
|
|
{
|
|
_ss_opt(0,&orgsgbufi);
|
|
#ifdef STRANGECONS
|
|
_ss_opt(0,&orgsgbufo);
|
|
#endif
|
|
}
|
|
|
|
eihalt()
|
|
{
|
|
tsleep(1);
|
|
}
|
|
|
|
#ifdef SLOWCHECK
|
|
|
|
int clksec()
|
|
{
|
|
time_t tim;
|
|
(void) time(&tim);
|
|
/* 1 second resolution, return hundredths */
|
|
return (int)(tim * 100);
|
|
}
|
|
|
|
#else
|
|
|
|
#ifdef _UCC
|
|
_asm("clksec: moveq #3,d0");
|
|
_asm(" os9 F$Time");
|
|
_asm(" move.l #0,d0");
|
|
_asm(" move.w d3,d0");
|
|
_asm(" rts");
|
|
#else
|
|
#include "clksec.a"
|
|
#endif
|
|
#endif
|
|
|
|
void
|
|
check_time()
|
|
{
|
|
int32 iss();
|
|
void tickle();
|
|
|
|
static long clkval;
|
|
long ntime, offset;
|
|
|
|
/* read elapsed real time (typ. 100 Hz) */
|
|
ntime=clksec();
|
|
|
|
/* resynchronize if the error is large (10 seconds or more) */
|
|
offset = ntime - clkval;
|
|
if (offset > (10000/MSPTICK) || offset < 0)
|
|
clkval = ntime;
|
|
|
|
/* Handle possibility of several missed ticks */
|
|
while (ntime != clkval){
|
|
fflush(NULL);
|
|
++clkval;
|
|
icmpclk();
|
|
tickle();
|
|
(void) iss();
|
|
}
|
|
}
|
|
/* Initialize asynch port "dev" */
|
|
int
|
|
asy_init(dev,arg1,arg2,bufsize)
|
|
char *arg1,*arg2;
|
|
int16 dev;
|
|
unsigned bufsize;
|
|
{
|
|
register unsigned base;
|
|
register struct asy *ap;
|
|
struct sgbuf sbuf;
|
|
unsigned i=0;
|
|
if (dev >= nasy)
|
|
return -1;
|
|
|
|
ap = &asy[dev];
|
|
|
|
/* ap->tty = malloc(strlen(arg2)+1);*/
|
|
strcpy(ap->tty,arg2);
|
|
|
|
if ( (IORser[dev]=open(ap->tty, S_IREAD+S_IWRITE)) < 0)
|
|
{ printf("asy %s: Open failed.\015\012", ap->tty);
|
|
fflush(stdout);
|
|
return -1;
|
|
}
|
|
_gs_opt(IORser[dev], &sbuf);
|
|
sbuf.sg_case = 0;
|
|
sbuf.sg_backsp = 0;
|
|
sbuf.sg_delete = 0;
|
|
sbuf.sg_echo = 0;
|
|
sbuf.sg_alf = 0;
|
|
sbuf.sg_nulls = 0;
|
|
sbuf.sg_pause = 0;
|
|
sbuf.sg_page = 0;
|
|
sbuf.sg_bspch = 0;
|
|
sbuf.sg_dlnch = 0;
|
|
sbuf.sg_eorch = 0;
|
|
sbuf.sg_eofch = 0;
|
|
sbuf.sg_rlnch = 0;
|
|
sbuf.sg_dulnch = 0;
|
|
sbuf.sg_psch = 0;
|
|
sbuf.sg_kbich = 0;
|
|
sbuf.sg_kbach = 0;
|
|
sbuf.sg_bsech = 0;
|
|
sbuf.sg_bellch = 0;
|
|
sbuf.sg_xon = 0;
|
|
sbuf.sg_xoff = 0;
|
|
sbuf.sg_tabcr = 0;
|
|
sbuf.sg_tabsiz = 0;
|
|
_ss_opt(IORser[dev], &sbuf);
|
|
|
|
switch(sbuf.sg_baud)
|
|
{
|
|
case 0: i = 50;
|
|
break;
|
|
case 1: i = 75;
|
|
break;
|
|
case 2: i = 110;
|
|
break;
|
|
case 3: i = 134;
|
|
break;
|
|
case 4: i = 150;
|
|
break;
|
|
case 5: i = 300;
|
|
break;
|
|
case 6: i = 600;
|
|
break;
|
|
case 7: i = 1200;
|
|
break;
|
|
case 8: i = 1800;
|
|
break;
|
|
case 10: i = 2400;
|
|
break;
|
|
case 12: i = 4800;
|
|
break;
|
|
case 14: i = 9600;
|
|
break;
|
|
case 15: i = 19200;
|
|
break;
|
|
case 16: i=38400;
|
|
break;
|
|
default: i= 0;
|
|
}
|
|
printf("asy %s :Open %i Baud, Ok.\015",ap->tty,i);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
asy_stop(iface)
|
|
struct interface *iface;
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* Asynchronous line I/O control (speed change not implemented */
|
|
asy_ioctl(interface,argc,argv)
|
|
struct interface *interface;
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
if(argc < 1){
|
|
printf("%d\015\012",asy[interface->dev].speed);
|
|
return 0;
|
|
}
|
|
return asy_speed(interface->dev,atoi(argv[0]));
|
|
}
|
|
|
|
|
|
/* Set asynch line speed */
|
|
int
|
|
asy_speed(dev,speed)
|
|
int dev;
|
|
int speed;
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Send a buffer to serial transmitter */
|
|
asy_output(dev,buf,cnt)
|
|
unsigned dev;
|
|
char *buf;
|
|
unsigned short cnt;
|
|
{
|
|
if(dev >= nasy)
|
|
return 0;
|
|
|
|
write(IORser[dev], buf, cnt);
|
|
}
|
|
|
|
/* Receive characters from asynch line
|
|
* Returns count of characters read
|
|
*/
|
|
unsigned
|
|
asy_recv(dev,buf,cnt)
|
|
int dev;
|
|
char *buf;
|
|
unsigned cnt;
|
|
{
|
|
register struct asy *ap;
|
|
register int charpend;
|
|
|
|
ap = &asy[dev];
|
|
|
|
if ( (charpend=_gs_rdy(IORser[dev])) < 0)
|
|
return 0;
|
|
|
|
charpend = read(IORser[dev], buf, min(charpend, cnt));
|
|
return charpend < 0 ? 0 : charpend;
|
|
}
|
|
|
|
|
|
int stxrdy(dev)
|
|
int dev;
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
/* dir in temp file (a lot of crap to do this in the 3.2 osk compiler).
|
|
Short/long listings. For FTP */
|
|
char *getenv();
|
|
void free();
|
|
|
|
FILE *
|
|
dir(path,full)
|
|
char *path;
|
|
int full;
|
|
{
|
|
FILE *fp, *fpo;
|
|
char *name = "dirfile", *cp;
|
|
char cmd[256], *fnamstr=cmd;
|
|
char disk[256];
|
|
FILE *tmpfile();
|
|
unsigned char ch;
|
|
int i,k,fp1;
|
|
register int j;
|
|
char *make_path();
|
|
char *ep, *np;
|
|
void filedir();
|
|
DIR *dt;
|
|
int dofree=0;
|
|
|
|
if ((ep=getenv("TMPDIR"))!=NULL)
|
|
{
|
|
np=make_path(ep,name,1);
|
|
dofree=1;
|
|
}
|
|
else
|
|
np=name;
|
|
|
|
strcpy(disk, path);
|
|
for (cp=disk; *cp && *++cp!='/'; )
|
|
;
|
|
*cp = '\0';
|
|
|
|
if(full){
|
|
sprintf(cmd,"(dir -de %s; echo; free %s; echo)>-%s",path,disk,np);
|
|
system(cmd);
|
|
} else {
|
|
|
|
fp1=creat(np,S_IREAD+S_IWRITE);
|
|
if ((dt=opendir(path))!=NULL)
|
|
{
|
|
closedir(dt);
|
|
strcat(path,"/*");
|
|
}
|
|
|
|
filedir(path,0,fnamstr);
|
|
if (*fnamstr=='\0')
|
|
close(fp1);
|
|
else
|
|
{
|
|
write(fp1,fnamstr,strlen(fnamstr));
|
|
write(fp1,"\015\012",2);
|
|
|
|
while(1)
|
|
{ filedir(path,1,fnamstr);
|
|
if (*fnamstr=='\0')
|
|
{
|
|
close(fp1);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
write(fp1,fnamstr,strlen(fnamstr));
|
|
write(fp1,"\015\012",2);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
NOTE, this ALMOST worked but added the path on a wildcard
|
|
dir which messed up remote mgets.
|
|
|
|
sprintf(cmd,"(dir -d %s; echo; free %s; echo)>-%s",path,disk,np);
|
|
system(cmd);
|
|
*/
|
|
}
|
|
fp = fopen(np,"r");
|
|
if((fpo = tmpfile())==NULLFILE)
|
|
return NULLFILE;
|
|
while ((i=fread(cmd,1,128,fp)))
|
|
{
|
|
k=0;
|
|
for(j=0;j<i;j++)
|
|
{
|
|
disk[k]=cmd[j];
|
|
k++;
|
|
if (cmd[j]=='\015')
|
|
{ disk[k]='\012';
|
|
k++;
|
|
}
|
|
}
|
|
fwrite(disk,1,k,fpo);
|
|
}
|
|
fflush(fpo);
|
|
rewind(fpo);
|
|
fclose(fp);
|
|
unlink(np);
|
|
if (dofree)
|
|
free(np);
|
|
return fpo;
|
|
}
|
|
|
|
/* dirutil.c
|
|
* OSK directory reading stuff.
|
|
* Matthias Bohlen
|
|
* Copyright 1987 Matthias Bohlen, All Rights Reserved.
|
|
* Permission granted for non-commercial copying and use, provided
|
|
* this notice is retained.
|
|
*/
|
|
|
|
static DIR *d;
|
|
static struct direct *r;
|
|
|
|
/* wildcard filename lookup */
|
|
void filedir (dirname, times, ret_str)
|
|
char *dirname;
|
|
int times;
|
|
char *ret_str;
|
|
{
|
|
DIR *d2;
|
|
register int masklen;
|
|
register char *cp;
|
|
int i;
|
|
char dname[80], filemask[80];
|
|
|
|
for (cp=dirname+strlen(dirname); cp>dirname && *--cp != '/'; )
|
|
;
|
|
strncpy(dname, dirname, cp-dirname);
|
|
dname[cp-dirname] = '\0';
|
|
strcpy(filemask, cp+1);
|
|
|
|
masklen = strlen(filemask);
|
|
|
|
if (times==0) { /* first time */
|
|
if ( (d=opendir(dname)) == NULL ) {
|
|
*ret_str = '\0';
|
|
return;
|
|
}
|
|
}
|
|
|
|
while (1) {
|
|
if ( (r=readdir(d)) == NULL ) {
|
|
*ret_str = '\0';
|
|
closedir(d);
|
|
return;
|
|
}
|
|
if (_cmpnam(r->d_name, filemask, masklen) == 0)
|
|
if (r->d_name[0] != '.') {
|
|
strcpy(ret_str, r->d_name);
|
|
|
|
strcat(dname,"/");
|
|
strcat(dname,ret_str);
|
|
if ((i=open(dname,S_IREAD))==-1)
|
|
{
|
|
if ((d2=opendir(dname))!=NULL)
|
|
{ closedir(d2);
|
|
strcat(ret_str,"/");
|
|
}
|
|
}
|
|
else
|
|
close(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
dodir(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
int i, stat;
|
|
char str[MAXCMD];
|
|
|
|
strcpy(str, "dir -e ");
|
|
for (i = 1; i < argc; i++) {
|
|
strcat(str, argv[i]);
|
|
strcat(str, " ");
|
|
}
|
|
|
|
|
|
stat = system(str);
|
|
|
|
return stat;
|
|
}
|
|
sysreset()
|
|
{
|
|
printf("\n no system reset function \n");
|
|
}
|
|
doshell(argc,argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
struct sgbuf sgbufi, sgbufo;
|
|
_gs_opt(0,&sgbufi);
|
|
#ifdef STRANGECONS
|
|
_gs_opt(1,&sgbufo);
|
|
#endif
|
|
_ss_opt(0,&orgsgbufi);
|
|
#ifdef STRANGECONS
|
|
_ss_opt(1,&orgsgbufo);
|
|
#endif
|
|
system("");
|
|
_ss_opt(0,&sgbufi);
|
|
#ifdef STRANGECONS
|
|
_ss_opt(1,&sgbufo);
|
|
#endif
|
|
}
|
|
|
|
/* close a pipe (not different in osk)? */
|
|
int pclose(i)
|
|
FILE *i;
|
|
{
|
|
fclose(i);
|
|
}
|
|
|
|
mkdir(s, m)
|
|
char *s;
|
|
int m;
|
|
{
|
|
char tmp[MAXCMD];
|
|
|
|
sprintf(tmp, "makdir %s", s);
|
|
if (system(tmp))
|
|
return -1;
|
|
/* if (chmod(s, m) < 0)
|
|
return -1;
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
|
|
rmdir(s)
|
|
char *s;
|
|
{
|
|
char tmp[MAXCMD];
|
|
|
|
sprintf(tmp, "deldir -f -q %s", s);
|
|
if (system(tmp))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
OpenPty()
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
char *getcwd(tmp,siz)
|
|
char *tmp;
|
|
int siz;
|
|
{
|
|
static int lock=0;
|
|
char *name="pdfile";
|
|
char *ep, *np, *make_path();
|
|
FILE *fil;
|
|
int dofree=0;
|
|
|
|
while (lock);
|
|
|
|
lock=1;
|
|
if ((ep=getenv("TMPDIR"))!=NULLCHAR)
|
|
{
|
|
dofree=1;
|
|
np=make_path(ep,name,1);
|
|
}
|
|
else
|
|
np = name;
|
|
sprintf(tmp,"pd >-%s",np);
|
|
system(tmp);
|
|
if ((fil=fopen(np,"r"))==NULL)
|
|
{
|
|
lock=0;
|
|
return NULL;
|
|
}
|
|
fgets(tmp,siz,fil);
|
|
fclose(fil);
|
|
unlink(np);
|
|
if (dofree)
|
|
free(np);
|
|
lock=0;
|
|
return name;
|
|
}
|
|
|
|
|
|
/* enabled this command with k28 -- it was incomplete. Tried to do it
|
|
in most portable way, though in SysV, it would be appropriate to feed
|
|
getcwd a null pointer and free the memory pointed to by getcwd's return
|
|
value. This command is used for "pwd" and "cd". - K5JB
|
|
*/
|
|
int
|
|
docd(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
static char tmp[MAXCMD];
|
|
char *getcwd();
|
|
extern char *homedir;
|
|
|
|
if(*argv[0] == 'c')
|
|
if(chdir(argc > 1 ? argv[1] : homedir) == -1){
|
|
printf("Can't change directory\n");
|
|
return 1;
|
|
}
|
|
|
|
if (getcwd(tmp, sizeof(tmp) - 2) != NULL)
|
|
printf("%s\n", tmp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
/* */
|
|
/* _secsince70() : Unix library (OS9/68000) */
|
|
/* ============= */
|
|
/* */
|
|
/* Author: K. Schmitt */
|
|
/* Compiler: Microware C Vers. 3.0 */
|
|
/* OS: OS9/68000 Vers. 2.2 */
|
|
/* */
|
|
/* Edition History */
|
|
/* =============== */
|
|
/* */
|
|
/* Ed. 0.00 Date 11/16/88 */
|
|
/* First version */
|
|
/* */
|
|
/***************************************************************************/
|
|
/* */
|
|
/* Description */
|
|
/* */
|
|
/*
|
|
returns # of secs past since 01/01/1970 GMT
|
|
|
|
*/
|
|
|
|
time_t _secsince70 (date)
|
|
char date []; /* yy/mm/dd/hh/mm/ss */
|
|
/* 0 1 2 3 4 5 */
|
|
{
|
|
struct tm time70, time_;
|
|
time_t mktime();
|
|
|
|
|
|
time70.tm_sec = 0;
|
|
time70.tm_min = 0;
|
|
time70.tm_hour = 0;
|
|
time70.tm_mday = 1;
|
|
time70.tm_mon = 0;
|
|
time70.tm_year = 70;
|
|
time70.tm_isdst = -1;
|
|
time_.tm_sec = (int) date[5];
|
|
time_.tm_min = (int) date[4];
|
|
time_.tm_hour = (int) date[3];
|
|
time_.tm_mday = (int) date[2];
|
|
time_.tm_mon = (int) date[1] - 1;
|
|
time_.tm_year = (int) date[0];
|
|
time_.tm_isdst = -1;
|
|
return (mktime(&time_.tm_sec) - mktime(&time70.tm_sec));
|
|
|
|
} /* end of _secsince70 */
|
|
|
|
/***************************************************************************/
|
|
/* */
|
|
/* stat() : Unix library (OS9/68000) */
|
|
/* ====== */
|
|
/* */
|
|
/* Author: K. Schmitt */
|
|
/* Compiler: Microware C Vers. 3.0 */
|
|
/* OS: OS9/68000 Vers. 2.2 */
|
|
/* */
|
|
/* Edition History */
|
|
/* =============== */
|
|
/* */
|
|
/* Ed. 0.00 Date 11/16/88 */
|
|
/* First version */
|
|
/* */
|
|
/***************************************************************************/
|
|
/* */
|
|
/* Description */
|
|
/* */
|
|
/*
|
|
|
|
NAME
|
|
stat, fstat - get file status
|
|
|
|
SYNOPSIS
|
|
#include <UNIX/stat.h>
|
|
|
|
int stat (path, buf)
|
|
char *path;
|
|
struct stat *buf;
|
|
|
|
int fstat (fildes, buf)
|
|
int fildes;
|
|
struct stat *buf;
|
|
|
|
DESCRIPTION
|
|
Path points to a path name naming a file. Read, write or
|
|
execute permission of the named file is not required, but
|
|
all directories listed in the path name leading to the file
|
|
must be searchable. Stat obtains information about the
|
|
named file.
|
|
|
|
Fstat obtains information about an open file known by the
|
|
file descriptor fildes, obtained from a successful open,
|
|
creat, dup, fcntl, or pipe system call.
|
|
|
|
Buf is a pointer to a stat structure into which information
|
|
is placed concerning the file.
|
|
|
|
The contents of the structure pointed to by buf include the
|
|
following members:
|
|
|
|
ushort st_mode; File mode
|
|
ino_t st_ino; Inode number
|
|
dev_t st_dev; ID of device containing a directory
|
|
entry for this file
|
|
dev_t st_rdev; ID of device. This entry is defined
|
|
only for character special or block
|
|
special files
|
|
short st_nlink; Number of links
|
|
ushort st_uid; User ID of the file's owner
|
|
ushort st_gid; Group ID of the file's group
|
|
off_t st_size; File size in bytes
|
|
time_t st_atime; Time of last access
|
|
time_t st_mtime; Time of last data modification
|
|
time_t st_ctime; Time of last file status change
|
|
Times measured in seconds since
|
|
00:00:00 GMT, Jan. 1, 1970
|
|
|
|
The following parameters are affected by different system
|
|
calls:
|
|
|
|
st_atime Time when file data was last accessed.
|
|
Changed by the following system calls: creat,
|
|
mknod, pipe, utime, and read.
|
|
|
|
st_mtime Time when data was last modified.
|
|
Changed by the following system calls: creat,
|
|
mknod, pipe, utime, and write.
|
|
|
|
st_ctime Time when file status was last changed.
|
|
Changed by the following system calls: chmod,
|
|
chown, creat, link, mknod, pipe, unlink, utime,
|
|
and write.
|
|
|
|
Stat will fail if one or more of the following are true:
|
|
|
|
[ENOTDIR] A component of the path prefix is not a
|
|
directory.
|
|
|
|
[ENOENT] The named file does not exist.
|
|
|
|
[EACCES] Search permission is denied for a component
|
|
of the path prefix.
|
|
|
|
[EFAULT] Buf or path points to an invalid address.
|
|
|
|
Fstat will fail if one or more of the following are true:
|
|
|
|
[EBADF] Fildes is not a valid open file descriptor.
|
|
|
|
[EFAULT] Buf points to an invalid address.
|
|
|
|
RETURN VALUE
|
|
Upon successful completion a value of 0 is returned.
|
|
Otherwise, a value of -1 is returned and errno is set to
|
|
indicate the error.
|
|
|
|
*/
|
|
|
|
#include "os9stat.h"
|
|
|
|
#include <direct.h>
|
|
|
|
extern time_t _secsince70 ();
|
|
|
|
int stat (fname, buf)
|
|
char fname [];
|
|
struct stat *buf;
|
|
{
|
|
int fd, ret;
|
|
DIR *dirp;
|
|
|
|
if ((fd = open (fname, S_IREAD)) == -1)
|
|
{
|
|
if ((dirp = opendir (fname)) == 0)
|
|
return (-1);
|
|
fd = dirp -> dd_fd;
|
|
}
|
|
else
|
|
{
|
|
dirp = 0;
|
|
}
|
|
|
|
ret = fstat (fd, buf);
|
|
if (dirp == 0) close (fd);
|
|
else closedir (dirp);
|
|
|
|
return (ret);
|
|
|
|
} /* end of stat */
|
|
|
|
|
|
|
|
int fstat (fd, buf)
|
|
int fd;
|
|
register struct stat *buf;
|
|
{
|
|
struct fildes fildes;
|
|
register int i;
|
|
register char *p;
|
|
char *malloc();
|
|
|
|
if (_gs_gfd (fd, &fildes, sizeof (struct fildes)) == -1)
|
|
return (-1);
|
|
|
|
buf -> st_uid = (unsigned short) (fildes.fd_own [0]);
|
|
buf -> st_gid = (unsigned short) (fildes.fd_own [1]);
|
|
buf -> st_mode = (unsigned short) (fildes.fd_att) & 0377;
|
|
buf -> st_nlink = (unsigned short) (fildes.fd_link);
|
|
|
|
for (i = 0, p = (char *) (&buf -> st_size); i < 4; i++)
|
|
{
|
|
*p++ = fildes.fd_fsize [i];
|
|
}
|
|
|
|
buf -> st_atime = buf -> st_mtime = _secsince70 (fildes.fd_date);
|
|
fildes.fd_dcr [3] = 0;
|
|
fildes.fd_dcr [4] = 0;
|
|
buf -> st_ctime = _secsince70 (fildes.fd_dcr);
|
|
if ((buf -> st_rdev = buf -> st_dev = malloc(30)) != (char *) 0)
|
|
{
|
|
_gs_devn (fd, buf -> st_dev);
|
|
}
|
|
|
|
return (0);
|
|
|
|
} /* end of fstat */
|
|
|
|
#ifndef _UCC
|
|
|
|
|
|
/***************************************************************************/
|
|
/* */
|
|
/* perror() : Unix library (OS9/68000) */
|
|
/* ======== */
|
|
/* */
|
|
/* Author: K. Schmitt / Ch. Engel */
|
|
/* Compiler: Microware C Vers. 3.0 */
|
|
/* OS: OS9/68000 Vers. 2.2 */
|
|
/* */
|
|
/* Edition History */
|
|
/* =============== */
|
|
/* */
|
|
/* Ed. 0.00 Date 11/11/88 */
|
|
/* First version */
|
|
/* */
|
|
/***************************************************************************/
|
|
/* */
|
|
/* Description */
|
|
/* */
|
|
/*
|
|
|
|
NAME
|
|
perror, sys_errlist, sys_nerr, errno - system error messages
|
|
|
|
SYNOPSIS
|
|
perror (s)
|
|
char *s;
|
|
|
|
int sys_nerr;
|
|
char *sys_errlist[ ];
|
|
|
|
int errno;
|
|
|
|
DESCRIPTION
|
|
Perror produces a short error message on the standard error,
|
|
describing the last error encountered during a system call
|
|
from a C program. First the argument string s is printed,
|
|
then a colon, then the message and a new-line. To be of
|
|
most use, the argument string should be the name of the
|
|
program that incurred the error. The error number is taken
|
|
from the external variable errno, which is set when errors
|
|
occur and cleared when non-erroneous calls are made.
|
|
|
|
To simplify variant formatting of messages, the vector of
|
|
message strings sys_errlist is provided; errno can be used
|
|
as an index in this table to get the message string without
|
|
the new-line. Sys_nerr is the largest message number
|
|
provided for in the table; it should be checked because new
|
|
error codes may be added to the system before they are added
|
|
to the table.
|
|
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
#define YES 1
|
|
#define NO 0
|
|
#define OK 0
|
|
#define ERR -1
|
|
|
|
#define ERRFILE "/dd/SYS/errmsg"
|
|
#define MAXERR 256
|
|
|
|
extern int errno;
|
|
|
|
int sys_nerr = MAXERR;
|
|
char *sys_errlist [MAXERR];
|
|
static int errstat = OK;
|
|
|
|
char *malloc ();
|
|
|
|
perror (s)
|
|
char *s;
|
|
{
|
|
static int first = YES;
|
|
FILE *errfile;
|
|
|
|
if (first)
|
|
{
|
|
first = NO;
|
|
if ((errfile = fopen (ERRFILE, "r")) == NULL)
|
|
{
|
|
errstat = ERR;
|
|
}
|
|
else
|
|
{
|
|
_build_errlist (errfile);
|
|
fclose (errfile);
|
|
}
|
|
}
|
|
|
|
if (errstat)
|
|
fprintf (stderr, "%s: %03d:%03d\n",
|
|
s, errno >> 8, errno & 0x0ff);
|
|
else
|
|
fprintf (stderr, "%s: %s\n", s, sys_errlist [errno&(MAXERR-1)]);
|
|
|
|
} /* end of perror */
|
|
|
|
#ifdef STATIC
|
|
static
|
|
#endif
|
|
_build_errlist (errfile)
|
|
FILE *errfile;
|
|
{
|
|
char message [1024], line [80];
|
|
register unsigned i;
|
|
register char *p;
|
|
|
|
for (i = 0; i < MAXERR ; i++)
|
|
sys_errlist [i] = NULL;
|
|
|
|
for (fgets (line, 80, errfile); ! feof (errfile); )
|
|
{
|
|
if (! isdigit (line [0]) || strlen (line) < 7)
|
|
{
|
|
fgets (line, 80, errfile);
|
|
continue;
|
|
}
|
|
|
|
i = (atoi (line) << 8) | atoi (line + 4);
|
|
for (p = line + 7; *p && isspace (*p); p++)
|
|
;
|
|
|
|
strcpy (message, p);
|
|
fgets (line, 80, errfile);
|
|
for ( ; line [0] != '\0' && ! isdigit (line [0]);
|
|
fgets (line, 80, errfile))
|
|
{
|
|
for (p = line; *p && isspace (*p); p++)
|
|
;
|
|
|
|
strcat (message, p);
|
|
}
|
|
|
|
if (i >= MAXERR) break;
|
|
|
|
if ((sys_errlist [i] = malloc (strlen (message) + 1)) ==
|
|
NULL)
|
|
{
|
|
errstat = ERR;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
strcpy (sys_errlist [i], message);
|
|
}
|
|
}
|
|
} /* end of _build_errlist */
|
|
|
|
FILE *tmpfile()
|
|
{
|
|
char *ep;
|
|
char fname[80];
|
|
int done=0;
|
|
int indx;
|
|
char *make_path();
|
|
char *tmp;
|
|
extern char *getenv();
|
|
FILE *fil, *fopen();
|
|
int access();
|
|
|
|
fname[0]='/';
|
|
fname[1]='a';
|
|
|
|
if ((ep = getenv("TMPDIR")) == NULLCHAR)
|
|
if ((ep = getenv("NETSPOOL")) == NULLCHAR)
|
|
perror("must set NETSPOOL env var\n");
|
|
done=0;
|
|
indx=0;
|
|
while (fname[1]<'z' && !done)
|
|
{ fname[2]='\0';
|
|
|
|
strcat(fname,".net_tmp");
|
|
tmp = make_path(ep,fname,0);
|
|
if (!access(tmp,0))
|
|
{ indx=indx+1;
|
|
fname[1]=fname[1]+1;
|
|
free(tmp);
|
|
}
|
|
else
|
|
{
|
|
if ((fil=fopen(tmp,"w+"))!=NULL)
|
|
{
|
|
tmpfils[indx].filptr=fil;
|
|
strcpy(tmpfils[indx].tmpnam,tmp);
|
|
done=1;
|
|
}
|
|
else
|
|
{
|
|
indx=indx+1;
|
|
fname[1]=fname[1]+1;
|
|
}
|
|
}
|
|
}
|
|
if (done)
|
|
{
|
|
free(tmp);
|
|
return fil;
|
|
}
|
|
else
|
|
return NULLFILE;
|
|
}
|
|
|
|
int tmpclose(t)
|
|
FILE *t;
|
|
{
|
|
int i=0;
|
|
|
|
while(i<26)
|
|
{
|
|
if (tmpfils[i].filptr==t)
|
|
{
|
|
fclose(t);
|
|
unlink(tmpfils[i].tmpnam);
|
|
tmpfils[i].filptr=NULL;
|
|
return 0;
|
|
}
|
|
i++;
|
|
}
|
|
/* printf("attempted to delete non-tempfile\n"); unavoidable but not important */
|
|
fclose(t);
|
|
return 0;
|
|
}
|
|
int rename(s,d)
|
|
char *s;
|
|
char *d;
|
|
{
|
|
char *d2;
|
|
char tmp[MAXCMD];
|
|
int access();
|
|
|
|
if (!access(d,0))
|
|
{
|
|
if (unlink(d))
|
|
{
|
|
printf("Can't rename file (no permission to unlink dup dest)\n");
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
/* strip path from destination */
|
|
{
|
|
d2=d;
|
|
while (*d != '\0')
|
|
{
|
|
if(*d++ == '/')
|
|
d2=d;
|
|
}
|
|
sprintf(tmp,"rename %s %s",s,d2);
|
|
system(tmp);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int fputc(c, fp)
|
|
int c;
|
|
FILE *fp;
|
|
{
|
|
putc(c,fp);
|
|
}
|
|
|
|
|
|
/***************************************************************************/
|
|
/* */
|
|
/* strtok() : Unix library (OS9/68000) */
|
|
/* ======== */
|
|
/* */
|
|
/* Author: Henry Spencer (UNIX stringlib from BIX) */
|
|
/* Compiler: Microware C Vers. 3.0 */
|
|
/* OS: OS9/68000 Vers. 2.2 */
|
|
/* */
|
|
/* Edition History */
|
|
/* =============== */
|
|
/* */
|
|
/* Ed. 0.00 Date 11/15/88 */
|
|
/* First version */
|
|
/* */
|
|
/***************************************************************************/
|
|
/* */
|
|
/* Description */
|
|
/* */
|
|
/*
|
|
|
|
char *strpbrk(s1, s2)
|
|
char *s1, *s2;
|
|
|
|
Strtok considers the string s1 to consist of a sequence of
|
|
zero or more text tokens separated by spans of one or more
|
|
characters from the separator string s2. The first call
|
|
(with pointer s1 specified) returns a pointer to the first
|
|
character of the first token, and will have written a NULL
|
|
character into s1 immediately following the returned token.
|
|
Subsequent calls with zero for the first argument, will work
|
|
through the string s1 in this way until no tokens remain.
|
|
The separator string s2 may be different from call to call.
|
|
When no token remains in s1, a NULL is returned.
|
|
*/
|
|
|
|
/*#define NULL 0 */
|
|
|
|
char *scanpoint = NULL;
|
|
char * /* NULL if no token left */
|
|
strtok(s, delim)
|
|
char *s;
|
|
register char *delim;
|
|
{
|
|
register char *scan;
|
|
char *tok;
|
|
register char *dscan;
|
|
|
|
if ((s == NULL) && (scanpoint == NULL))
|
|
return(NULL);
|
|
|
|
if (s != NULL)
|
|
scan = s;
|
|
else
|
|
scan = scanpoint;
|
|
|
|
/*
|
|
* Scan leading delimiters.
|
|
*/
|
|
for (; *scan != '\0'; scan++)
|
|
{
|
|
for (dscan = delim; *dscan != '\0'; dscan++)
|
|
{
|
|
if (*scan == *dscan)
|
|
break;
|
|
}
|
|
|
|
if (*dscan == '\0')
|
|
break;
|
|
}
|
|
|
|
if (*scan == '\0')
|
|
{
|
|
scanpoint = NULL;
|
|
return(NULL);
|
|
}
|
|
|
|
tok = scan;
|
|
|
|
/*
|
|
* Scan token.
|
|
*/
|
|
for (; *scan != '\0'; scan++)
|
|
{
|
|
for (dscan = delim; *dscan != '\0';) /* ++ moved down. */
|
|
{
|
|
if (*scan == *dscan++)
|
|
{
|
|
scanpoint = scan+1;
|
|
*scan = '\0';
|
|
return(tok);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Reached end of string.
|
|
*/
|
|
scanpoint = NULL;
|
|
return(tok);
|
|
|
|
} /* end of strtok */
|
|
|
|
|
|
#endif
|
|
/* E O F */
|