#line 2 "osdep/dosgen" /* So compiler knows orig name of this file.*/ /* * $Id: dosgen 7281 2004-04-05 01:06:15Z amk $ * * 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-2001 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. */ void 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], *p; if(Pmaster && Pmaster->home_dir) p = Pmaster->home_dir; else { sprintf(buf, "%c:\\", _getdrive() + 'A' - 1); p = buf; } hlen = strlen(p); if((home=(char *)malloc(((size_t)hlen + 1) * sizeof(char))) == NULL){ emlwrite("Problem allocating space for home dir", NULL); return(0); } strcpy(home, p); } 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; size_t avail, alloced, incr = 1024; 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{ #define MAX(x,y) ((x) > (y) ? (x) : (y)) avail = alloced = MAX(sbuf.st_size, incr); if(!(sbuf.st_mode & S_IFDIR)){ if(e) sprintf(e, "\007Not a directory: \"%s\"", dn); return(NULL); } } if((names=(char *)malloc(alloced * sizeof(char))) == NULL){ if(e) sprintf(e, "\007Can't malloc space for file names"); 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; l = strlen(p); while(avail < l+1){ char *oldnames; alloced += incr; avail += incr; oldnames = names; if((names = (char *)realloc((void *)names, alloced * sizeof(char))) == NULL){ if(e) sprintf(e, "\007Can't malloc enough space for file names"); return(NULL); } np = names + (np-oldnames); } avail -= (l+1); 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; size_t 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 && strlen(home)+strlen(x)= 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 */ void fixpath(name, len) char *name; size_t len; { char file[_MAX_PATH]; int dr; if(!len) return; /* 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] != '\\') strncat(file, "\\", sizeof(file)-1-strlen(file)); /* add file name */ strncat(file, &name[2], sizeof(file)-1-strlen(file)); } else return; } else return; /* fully qualified with drive and path! */ } else if(name[0] == '\\' && name[1] != '\\') { /* no drive spec! */ sprintf(file, "%c:%.*s", _getdrive()+'A'-1, len-3, name); } else if(name[0] == '\\' && name[1] == '\\'){ /* Windows network drive */ return; } else{ if(Pmaster && !(gmode & MDCURDIR)){ strncpy(file, ((gmode & MDTREE) || opertree[0]) ? opertree : gethomedir(NULL), sizeof(file)-1); file[sizeof(file)-1] = '\0'; } else if(!_getcwd(file, sizeof(file))) /* no qualification */ return; if(*name){ /* if name, append it */ if(*file && file[strlen(file)-1] != '\\') strncat(file, "\\", sizeof(file)-1-strlen(file)); strncat(file, name, sizeof(file)-1-strlen(file)); } } strncpy(name, file, len-1); /* copy back to real buffer */ name[len-1] = '\0'; /* tie off just in case */ } /* * 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 */ } /* * This routine is derived from BSD4.3 code, * Copyright (c) 1987 Regents of the University of California. * All rights reserved. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)mktemp.c 5.7 (Berkeley) 6/27/88"; #endif /* LIBC_SCCS and not lint */ static char * was_nonexistent_tmp_name(as, create_it, ext) char *as; int create_it; char *ext; { register char *start, *trv; char treplace; struct stat sbuf; unsigned pid; static unsigned n = 0; int fd; pid = ((unsigned)getpid() * 100) + n++; /* extra X's get set to 0's */ for(trv = as; *trv; ++trv) ; /* * We should probably make the name random instead of having it * be the pid. */ while(*--trv == 'X'){ *trv = (pid % 10) + '0'; pid /= 10; } /* add the extension, enough room guaranteed by caller */ if(ext){ strcat(as, "."); strcat(as, ext); } /* * Check for write permission on target directory; if you have * six X's and you can't write the directory, this will run for * a *very* long time. */ for(start = ++trv; trv > as && *trv != '\\'; --trv) ; if(*trv == '\\'){ if((trv - as == 2) && isalpha(as[0]) && as[1] == ':') trv++; treplace = *trv; *trv = '\0'; if(stat(as==trv ? "\\" : as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) return((char *)NULL); *trv = treplace; } else if (stat(".", &sbuf) == -1) return((char *)NULL); for(;;){ if(stat(as, &sbuf)){ /* stat failed */ if(errno == ENOENT){ /* no such file, success */ /* * If create_it is set, create the file so that the * evil ones don't have a chance to put something there * that they can read or write before we create it * ourselves. */ if(!create_it || ((fd=open(as, O_CREAT|O_EXCL|O_WRONLY,0600)) >= 0 && close(fd) == 0)) return(as); } else /* failed for unknown reason */ return((char *)NULL); } for(trv = start;;){ if(!*trv) return((char *)NULL); /* * Change the digits from the initial values into * lower case letters and try again. */ if(*trv == 'z') *trv++ = 'a'; else{ if(isdigit((unsigned char)*trv)) *trv = 'a'; else ++*trv; break; } } } /*NOTREACHED*/ } /* * This routine is derived from BSD4.3 code, * Copyright (c) 1988 Regents of the University of California. * All rights reserved. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)tmpnam.c 4.5 (Berkeley) 6/27/88"; #endif /* LIBC_SCCS and not lint */ /*---------------------------------------------------------------------- Return a unique file name in a given directory. This is not quite the same as the usual tempnam() function, though it is similar. We want it to use the TMP/TMPDIR environment variable only if dir is NULL, instead of using it regardless if it is set. We also want it to be safer than tempnam(). If we return a filename, we are saying that the file did not exist at the time this function was called (and it wasn't a symlink pointing to a file that didn't exist, either). If dir is NULL this is a temp file in a public directory. In that case we create the file with permission 0600 before returning. Args: dir -- The directory to create the name in prefix -- Prefix of the name Result: Malloc'd string equal to new name is returned. It must be free'd by the caller. Returns the string on success and NULL on failure. ----*/ char * temp_nam(dir, prefix) char *dir, *prefix; { struct stat buf; size_t l, ll; char *f, *name; if(!(name = (char *)malloc((unsigned int)NFILEN))) return((char *)NULL); if(!dir && (f = getenv("TMPDIR")) && !stat(f, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(f, WRITE_ACCESS)){ strncpy(name, f, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } if(!dir && (f = getenv("TMP")) && !stat(f, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(f, WRITE_ACCESS)){ strncpy(name, f, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } if(!dir && (f = getenv("TEMP")) && !stat(f, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(f, WRITE_ACCESS)){ strncpy(name, f, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } if(dir){ strncpy(name, dir, NFILEN-1); name[NFILEN-1] = '\0'; if(!*dir || (isalpha(*dir) && *(dir+1) == ':' && !*(dir+2))) strcat(name, "\\"); if((!stat(name, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR) && !can_access(name, WRITE_ACCESS)){ strncpy(name, dir, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } } #ifndef P_tmpdir #define P_tmpdir "\\tmp" #endif if(!stat(P_tmpdir, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(P_tmpdir, WRITE_ACCESS)){ strncpy(name, P_tmpdir, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } free(name); return((char *)NULL); done: if(name[0] && *((f = &name[l=strlen(name)]) - 1) != '\\' && l+1 < NFILEN){ *f++ = '\\'; *f = '\0'; l++; } if(prefix && (ll = strlen(prefix)) && l+ll < NFILEN){ strcpy(f, prefix); f += ll; l += ll; } if(l+6 < NFILEN) strcpy(f, "XXXXXX"); else{ free(name); return((char *)NULL); } return(was_nonexistent_tmp_name(name, 1, NULL)); } /*---------------------------------------------------------------------- Like temp_nam but create a unique name with an extension. Result: Malloc'd string equal to new name is returned. It must be free'd by the caller. Returns the string on success and NULL on failure. ----*/ char * temp_nam_ext(dir, prefix, ext) char *dir, *prefix, *ext; { struct stat buf; size_t l, ll; char *f, *name; if(ext == NULL || *ext == '\0') return(temp_nam(dir, prefix)); if(!(name = (char *)malloc((unsigned int)NFILEN))) return((char *)NULL); if(!dir && (f = getenv("TMPDIR")) && !stat(f, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(f, WRITE_ACCESS)){ strncpy(name, f, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } if(!dir && (f = getenv("TMP")) && !stat(f, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(f, WRITE_ACCESS)){ strncpy(name, f, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } if(!dir && (f = getenv("TEMP")) && !stat(f, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(f, WRITE_ACCESS)){ strncpy(name, f, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } if(dir){ strncpy(name, dir, NFILEN-1); name[NFILEN-1] = '\0'; if(!*dir || (isalpha(*dir) && *(dir+1) == ':' && !*(dir+2))) strcat(name, "\\"); if((!stat(name, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR) && !can_access(name, WRITE_ACCESS)){ strncpy(name, dir, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } } #ifndef P_tmpdir #define P_tmpdir "\\tmp" #endif if(!stat(P_tmpdir, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR && !can_access(P_tmpdir, WRITE_ACCESS)){ strncpy(name, P_tmpdir, NFILEN-1); name[NFILEN-1] = '\0'; goto done; } free(name); return((char *)NULL); done: if(name[0] && *((f = &name[l=strlen(name)]) - 1) != '\\' && l+1 < NFILEN){ *f++ = '\\'; *f = '\0'; l++; } if(prefix && (ll = strlen(prefix)) && l+ll < NFILEN){ strcpy(f, prefix); f += ll; l += ll; } if(l+6+strlen(ext)+1 < NFILEN) strcpy(f, "XXXXXX"); else{ free(name); return((char *)NULL); } return(was_nonexistent_tmp_name(name, 1, ext)); } /* * 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]; char *t; if(!((dir && *dir) || (dir = getenv("TMPDIR")) || (dir = getenv("TMP")) || (dir = getenv("TEMP")))) if(!(getcwd(dir = tmp, _MAX_PATH) && fexist(dir, "w", (off_t *) NULL) == FIOSUC)) dir = "c:\\"; if(t = temp_nam_ext(dir, "ae", "txt")){ strncpy(name, t, NFILEN-1); name[NFILEN-1] = '\0'; free(t); } else{ emlwrite("Unable to construct temp file name", NULL); name[0] = '\0'; } } /* * 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 */ void 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(collation, ctype) int collation; int ctype; { extern int collator(); /* strcoll isn't declared on all systems */ #ifdef LC_COLLATE char *status = NULL; #endif pcollator = strucmp; #ifdef LC_COLLATE if(collation){ /* * 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 if(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); }