home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.uv.es
/
2014.11.ftp.uv.es.tar
/
ftp.uv.es
/
pub
/
unix
/
pine4.10.tar.gz
/
pine4.10.tar
/
pine4.10
/
pico
/
osdep
/
dosgen
< prev
next >
Wrap
Text File
|
1998-12-15
|
19KB
|
900 lines
#line 2 "osdep/dosgen" /* So compiler knows orig name of this file.*/
/*
* $Id: dosgen,v 1.22 1998/12/16 03:23:16 mikes Exp $
*
* Program: Operating system dependent routines - MS DOS Generic
*
*
* Michael Seibel
* Networks and Distributed Computing
* Computing and Communications
* University of Washington
* Administration Builiding, AG-44
* Seattle, Washington, 98195, USA
* Internet: mikes@cac.washington.edu
*
* Please address all bugs and comments to "pine-bugs@cac.washington.edu"
*
*
* Pine and Pico are registered trademarks of the University of Washington.
* No commercial use of these trademarks may be made without prior written
* permission of the University of Washington.
*
* Pine, Pico, and Pilot software and its included text are Copyright
* 1989-1998 by the University of Washington.
*
* The full text of our legal notices is contained in the file called
* CPYRIGHT, included with this distribution.
*
*
* Notes:
* - This file should contain the cross section of functions useful
* in both DOS and Windows ports of pico.
*
*/
/*
* picosigs - Install any handlers for the signals we're interested
* in catching.
*/
picosigs()
{
/* no op */
}
/*
* Useful definitions...
*/
#ifdef MOUSE
static int mexist = 0; /* is the mouse driver installed? */
static int nbuttons; /* number of buttons on the mouse */
static unsigned mnoop;
#endif
static unsigned char okinfname[32] = {
0, 0, /* ^@ - ^G, ^H - ^O */
0, 0, /* ^P - ^W, ^X - ^_ */
0x80, 0x17, /* SP - ' , ( - / */
0xff, 0xe4, /* 0 - 7 , 8 - ? */
0x7f, 0xff, /* @ - G , H - O */
0xff, 0xe9, /* P - W , X - _ */
0x7f, 0xff, /* ` - g , h - o */
0xff, 0xf6, /* p - w , x - DEL */
0, 0, /* > DEL */
0, 0, /* > DEL */
0, 0, /* > DEL */
0, 0, /* > DEL */
0, 0 /* > DEL */
};
/*
* fallowc - returns TRUE if c is allowable in filenames, FALSE otw
*/
fallowc(c)
int c;
{
return(okinfname[c>>3] & 0x80>>(c&7));
}
#ifdef MOUSE
/*
* end_mouse - a no-op on DOS/Windows
*/
void
end_mouse()
{
}
/*
* mouseexist - function to let outsiders know if mouse is turned on
* or not.
*/
mouseexist()
{
return(mexist);
}
#endif /* MOUSE */
/*
* fexist - returns TRUE if the file exists, FALSE otherwise
*/
fexist(file, m, l)
char *file, *m;
off_t *l;
{
struct stat sbuf;
if(l != NULL)
*l = (off_t)0;
if(stat(file, &sbuf) < 0){
if(errno == ENOENT) /* File not found */
return(FIOFNF);
else
return(FIOERR);
}
if(l != NULL)
*l = (off_t)sbuf.st_size;
if(sbuf.st_mode & S_IFDIR)
return(FIODIR);
else if(*m == 't') /* no links, just say yes */
return(FIOSUC);
if(m[0] == 'r') /* read access? */
return((S_IREAD & sbuf.st_mode) ? FIOSUC : FIONRD);
else if(m[0] == 'w') /* write access? */
return((S_IWRITE & sbuf.st_mode) ? FIOSUC : FIONWT);
else if(m[0] == 'x') /* execute access? */
return((S_IEXEC & sbuf.st_mode) ? FIOSUC : FIONEX);
return(FIOERR); /* what? */
}
/*
* isdir - returns true if fn is a readable directory, false otherwise
* silent on errors (we'll let someone else notice the problem;)).
*/
isdir(fn, l, d)
char *fn;
long *l;
time_t *d;
{
struct stat sbuf;
if(l)
*l = 0;
if(stat(fn, &sbuf) < 0)
return(0);
if(l)
*l = sbuf.st_size;
if(d)
*d = sbuf.st_mtime;
return(sbuf.st_mode & S_IFDIR);
}
/*
* gethomedir - returns the users home directory
* Note: home is malloc'd for life of pico
*/
char *gethomedir(l)
int *l;
{
static char *home = NULL;
static short hlen = 0;
if(home == NULL){
char buf[NLINE];
sprintf(buf, "%c:\\", _getdrive() + 'A' - 1);
hlen = strlen(buf);
if((home=(char *)malloc(((size_t)hlen + 1) * sizeof(char))) == NULL){
emlwrite("Problem allocating space for home dir", NULL);
return(0);
}
strcpy(home, buf);
}
if(l)
*l = hlen;
return(home);
}
/*
* homeless - returns true if given file does not reside in the current
* user's home directory tree.
*/
homeless(f)
char *f;
{
char *home;
int len;
home = gethomedir(&len);
return(strncmp(home, f, len));
}
/*
* errstr - return system error string corresponding to given errno
* Note: strerror() is not provided on all systems, so it's
* done here once and for all.
*/
char *errstr(err)
int err;
{
return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL);
}
/*
* getfnames - return all file names in the given directory in a single
* malloc'd string. n contains the number of names
*/
char *getfnames(dn, pat, n, e)
char *dn, *pat, *e;
int *n;
{
int status;
long l;
char *names, *np, *p;
char buf[NLINE];
struct stat sbuf;
#ifdef WIN32
struct _finddata_t dbuf;
long findrv;
#else
struct find_t dbuf; /* opened directory */
#endif
*n = 0;
if(stat(dn, &sbuf) < 0){
if(e)
sprintf(e, "\007Dir \"%s\": %s", dn, strerror(errno));
return(NULL);
}
else{
l = sbuf.st_size;
if(!(sbuf.st_mode & S_IFDIR)){
if(e)
sprintf(e, "\007Not a directory: \"%s\"", dn);
return(NULL);
}
}
if((names=(char *)malloc(sizeof(char)*3072)) == NULL){
if(e)
sprintf(e, "\007Can't malloc space for file names", NULL);
return(NULL);
}
np = names;
strcpy(buf, dn);
sprintf(buf, "%s%s%s*%s%s", dn,
(dn[strlen(dn)-1] == '\\') ? "" : "\\",
(pat && *pat) ? pat : "",
(pat && *pat && strchr(pat, '.')) ? "" : ".",
(pat && *pat && strchr(pat, '.')) ? "" : "*");
#ifdef WIN32
if((findrv = _findfirst(buf, &dbuf)) < 0){
#else
if(_dos_findfirst(buf, _A_NORMAL|_A_SUBDIR, &dbuf) != 0){
#endif
if(e)
sprintf(e, "Can't find first file in \"%s\"", dn);
free((char *) names);
return(NULL);
}
do{
(*n)++;
p = dbuf.name;
while((*np++ = *p++) != '\0')
;
}
#ifdef WIN32
while(_findnext(findrv, &dbuf) == 0);
_findclose(findrv);
#else
while(_dos_findnext(&dbuf) == 0);
#endif
return(names);
}
/*
* fioperr - given the error number and file name, display error
*/
void
fioperr(e, f)
int e;
char *f;
{
switch(e){
case FIOFNF: /* File not found */
emlwrite("\007File \"%s\" not found", f);
break;
case FIOEOF: /* end of file */
emlwrite("\007End of file \"%s\" reached", f);
break;
case FIOLNG: /* name too long */
emlwrite("\007File name \"%s\" too long", f);
break;
case FIODIR: /* file is a directory */
emlwrite("\007File \"%s\" is a directory", f);
break;
case FIONWT:
emlwrite("\007Write permission denied: %s", f);
break;
case FIONRD:
emlwrite("\007Read permission denied: %s", f);
break;
case FIONEX:
emlwrite("\007Execute permission denied: %s", f);
break;
default:
emlwrite("\007File I/O error: %s", f);
}
}
/*
* pfnexpand - pico's function to expand the given file name if there is
* a leading '~'
*/
char *pfnexpand(fn, len)
char *fn;
int len;
{
register char *x, *y, *z;
char *home = NULL;
char name[_MAX_PATH];
if(*fn == '~' && *(x = fn + 1) == '\\') {
if(!(home = (char *) getenv("HOME"))
&& getenv("HOMEDRIVE") && getenv("HOMEPATH"))
sprintf(home = name, "%s%s",
(char *) getenv("HOMEDRIVE"), (char *) getenv("HOMEPATH"));
if(home){
/* make room for expanded path */
for(z = x + strlen(x), y = fn + strlen(x) + strlen(home);
z >= x;
*y-- = *z--)
;
/* and insert the expanded address */
for(x = fn, y = home; *y != '\0'; *x++ = *y++)
;
}
}
return(fn);
}
/*
* fixpath - make the given pathname into an absolute path
*/
fixpath(name, len)
char *name;
int len;
{
char file[_MAX_PATH];
int dr;
if(!len)
return(0);
/* return the full path of given file, so drive spec? */
if(name[1] == ':' && isalpha((unsigned char) name[0])){
if(name[2] != '\\'){ /* including path? */
dr = toupper((unsigned char)name[0]) - 'A' + 1;
if(_getdcwd(dr, file, _MAX_PATH) != NULL){
if(file[strlen(file)-1] != '\\')
strcat(file, "\\");
strcat(file, &name[2]); /* add file name */
}
else
return(0);
}
else
return(1); /* fully qualified with drive and path! */
}
else if(name[0] == '\\') { /* no drive spec! */
sprintf(file, "%c:%s", _getdrive()+'A'-1, name);
}
else{
if(Pmaster && !(gmode & MDCURDIR))
strcpy(file, ((gmode & MDTREE) || opertree[0])
? opertree : gethomedir(NULL));
else if(!_getcwd(file, _MAX_PATH)) /* no qualification */
return(0);
if(*name){ /* if name, append it */
if(*file && file[strlen(file)-1] != '\\')
strcat(file, "\\");
strcat(file, name);
}
}
strncpy(name, file, len); /* copy back to real buffer */
name[len-1] = '\0'; /* tie off just in case */
return(1);
}
/*
* compresspath - given a base path and an additional directory, collapse
* ".." and "." elements and return absolute path (appending
* base if necessary).
*
* returns 1 if OK,
* 0 if there's a problem
* new path, by side effect, if things went OK
*/
compresspath(base, path, len)
char *base, *path;
int len;
{
register int i;
int depth = 0;
char *p;
char *stack[32];
char pathbuf[NLINE];
#define PUSHD(X) (stack[depth++] = X)
#define POPD() ((depth > 0) ? stack[--depth] : "")
strcpy(pathbuf, path);
fixpath(pathbuf, len);
p = pathbuf;
for(i=0; pathbuf[i] != '\0'; i++){ /* pass thru path name */
if(pathbuf[i] == C_FILESEP){
if(p != pathbuf)
PUSHD(p); /* push dir entry */
p = &pathbuf[i+1]; /* advance p */
pathbuf[i] = '\0'; /* cap old p off */
continue;
}
if(pathbuf[i] == '.'){ /* special cases! */
if(pathbuf[i+1] == '.' /* parent */
&& (pathbuf[i+2] == C_FILESEP || pathbuf[i+2] == '\0')){
if(!strcmp(POPD(),"")) /* bad news! */
return(0);
i += 2;
p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
}
else if(pathbuf[i+1] == C_FILESEP || pathbuf[i+1] == '\0'){
i++;
p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
}
}
}
if(*p != '\0')
PUSHD(p); /* get last element */
path[0] = '\0';
for(i = 0; i < depth; i++){
strcat(path, S_FILESEP);
strcat(path, stack[i]);
}
return(1); /* everything's ok */
}
/*
* tmpname - return a temporary file name in the given buffer, the filename
* is in the directory dir unless dir is NULL
*/
void
tmpname(dir, name)
char *dir;
char *name;
{
char tmp[_MAX_PATH];
if(!((dir && *dir) || (dir = getenv("TEMP"))))
if(!(getcwd(dir = tmp, _MAX_PATH)
&& fexist(dir, "w", (off_t *) NULL) == FIOSUC))
dir = "c:\\";
sprintf(name, "%s.txt", tempnam(dir, "ae"));
}
/*
* Take a file name, and from it
* fabricate a buffer name. This routine knows
* about the syntax of file names on the target system.
* I suppose that this information could be put in
* a better place than a line of code.
*/
void
makename(bname, fname)
char bname[];
char fname[];
{
register char *cp1;
register char *cp2;
cp1 = &fname[0];
while (*cp1 != 0)
++cp1;
while (cp1!=&fname[0] && cp1[-1]!='\\')
--cp1;
cp2 = &bname[0];
while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
*cp2++ = *cp1++;
*cp2 = 0;
}
/*
* copy - copy contents of file 'a' into a file named 'b'. Return error
* if either isn't accessible or is a directory
*/
copy(a, b)
char *a, *b;
{
int in, out, n, rv = 0;
char *cb;
struct stat tsb, fsb;
if(stat(a, &fsb) < 0){ /* get source file info */
emlwrite("Can't Copy: %s", errstr(errno));
return(-1);
}
if(!(fsb.st_mode&S_IREAD)){ /* can we read it? */
emlwrite("\007Read permission denied: %s", a);
return(-1);
}
if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */
emlwrite("\007Can't copy: %s is a directory", a);
return(-1);
}
if(stat(b, &tsb) < 0){ /* get dest file's mode */
switch(errno){
case ENOENT:
break; /* these are OK */
default:
emlwrite("\007Can't Copy: %s", errstr(errno));
return(-1);
}
}
else{
if(!(tsb.st_mode&S_IWRITE)){ /* can we write it? */
emlwrite("\007Write permission denied: %s", b);
return(-1);
}
if((tsb.st_mode&S_IFMT) == S_IFDIR){ /* is it directory? */
emlwrite("\007Can't copy: %s is a directory", b);
return(-1);
}
if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){
emlwrite("\007Identical files. File not copied", NULL);
return(-1);
}
}
if((in = open(a, _O_RDONLY)) < 0){
emlwrite("Copy Failed: %s", errstr(errno));
return(-1);
}
if((out=creat(b, fsb.st_mode&0xfff)) < 0){
emlwrite("Can't Copy: %s", errstr(errno));
close(in);
return(-1);
}
if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){
emlwrite("Can't allocate space for copy buffer!", NULL);
close(in);
close(out);
return(-1);
}
while(1){ /* do the copy */
if((n = read(in, cb, NLINE)) < 0){
emlwrite("Can't Read Copy: %s", errstr(errno));
rv = -1;
break; /* get out now */
}
if(n == 0) /* done! */
break;
if(write(out, cb, n) != n){
emlwrite("Can't Write Copy: %s", errstr(errno));
rv = -1;
break;
}
}
free(cb);
close(in);
close(out);
return(rv);
}
/*
* Open a file for writing. Return TRUE if all is well, and FALSE on error
* (cannot create).
*/
ffwopen(fn, readonly)
char *fn;
int readonly;
{
extern FIOINFO g_pico_fio;
g_pico_fio.flags = FIOINFO_WRITE;
if ((g_pico_fio.fp = fopen(g_pico_fio.name = fn, "w")) == NULL) {
emlwrite("Cannot open file for writing", NULL);
return (FIOERR);
}
#ifdef MODE_READONLY
if(readonly)
chmod(fn, MODE_READONLY); /* fix access rights */
#endif
return (FIOSUC);
}
/*
* Close a file. Should look at the status in all systems.
*/
ffclose()
{
extern FIOINFO g_pico_fio;
if (fclose(g_pico_fio.fp) != FALSE) {
emlwrite("Error closing file", NULL);
return(FIOERR);
}
return(FIOSUC);
}
/*
* ffelbowroom - make sure the destination's got enough room to receive
* what we're about to write...
*/
ffelbowroom()
{
return(TRUE);
}
/*
* worthit - generic sort of test to roughly gage usefulness of using
* optimized scrolling.
*
* note:
* returns the line on the screen, l, that the dot is currently on
*/
worthit(l)
int *l;
{
int i; /* l is current line */
unsigned below; /* below is avg # of ch/line under . */
*l = doton(&i, &below);
below = (i > 0) ? below/(unsigned)i : 0;
return(below > 3);
}
/*
* o_insert - optimize screen insert of char c
*/
o_insert(c)
int c;
{
return(0);
}
/*
* o_delete - optimized character deletion
*/
o_delete()
{
return(0);
}
/*
* pico_new_mail - just checks mtime and atime of mail file and notifies user
* if it's possible that they have new mail.
*/
pico_new_mail()
{
return(0);
}
/*
* time_to_check - checks the current time against the last time called
* and returns true if the elapsed time is > timeo
*/
time_to_check()
{
static time_t lasttime = 0L;
if(!timeo)
return(FALSE);
if(time((long *) 0) - lasttime > (time_t)timeo){
lasttime = time((long *) 0);
return(TRUE);
}
else
return(FALSE);
}
/*
* sstrcasecmp - compare two pointers to strings case independently
*/
sstrcasecmp(s1, s2)
QcompType *s1, *s2;
{
return((*pcollator)(*(char **)s1, *(char **)s2));
}
int
strucmp(o, r)
char *o, *r;
{
return(o ? (r ? stricmp(o, r) : 1) : (r ? -1 : 0));
}
int
struncmp(o, r, n)
char *o, *r;
int n;
{
return(o ? (r ? strnicmp(o, r, n) : 1) : (r ? -1 : 0));
}
/*
* chkptinit -- initialize anything we need to support composer
* checkpointing
*/
chkptinit(file, n)
char *file;
int n;
{
if(!file[0]){
long gmode_save = gmode;
if(gmode&MDCURDIR)
gmode &= ~MDCURDIR; /* so fixpath will use home dir */
strcpy(file, "#picoTM0.txt");
fixpath(file, NLINE);
gmode = gmode_save;
}
else{
int l = strlen(file);
if(file[l-1] != '\\'){
file[l++] = '\\';
file[l] = '\0';
}
strcpy(file + l, "#picoTM0.txt");
}
if(fexist(file, "r", (off_t *)NULL) == FIOSUC){ /* does file exist? */
char copy[NLINE];
strcpy(copy, "#picoTM1.txt");
fixpath(copy, NLINE);
rename(file, copy); /* save so we don't overwrite it */
}
unlink(file);
}
void
set_collation()
{
char *status = NULL;
extern int collator(); /* strcoll isn't declared on all systems */
pcollator = strucmp;
#ifdef LC_COLLATE
/*
* This may not have the desired effect, if collator is not
* defined to be strcoll in os.h and strcmp and friends
* don't know about locales. If your system does have strcoll
* but we haven't defined collator to be strcoll in os.h, let us know.
*/
status = setlocale(LC_COLLATE, "");
/*
* If there is an error or if the locale is the "C" locale, then we
* don't want to use strcoll because in the default "C" locale strcoll
* uses strcmp ordering and we want strucmp ordering.
*
* The test for "C" isn't really correct, since status does not have to
* be "C" even if we're in the "C" locale. But this works on some systems.
*/
if(status && !(status[0] == 'C' && status[1] == '\0'))
pcollator = collator;
#endif
#ifdef LC_CTYPE
(void)setlocale(LC_CTYPE, "");
#endif
}
/*
* sleep the given number of microseconds
*/
ssleep(s)
clock_t s;
{
s += clock();
while(s > clock())
;
}
/*
* sleep the given number of seconds
*/
sleep(t)
int t;
{
time_t out = (time_t)t + time((long *) 0);
while(out > time((long *) 0))
;
}
/*
* map the ftruncate call into DOS' chsize
*/
int
truncate(file, size)
char *file;
long size;
{
int fd, rv = -1;
if((fd = open(file, O_RDWR | O_CREAT | S_IREAD | S_IWRITE)) != -1){
if(chsize(fd, size) == 0)
rv = 0;
close(fd);
}
return(rv);
}