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 >
Text File  |  1998-12-15  |  19KB  |  900 lines

  1. #line 2 "osdep/dosgen"        /* So compiler knows orig name of this file.*/
  2. /*
  3.  * $Id: dosgen,v 1.22 1998/12/16 03:23:16 mikes Exp $
  4.  *
  5.  * Program:    Operating system dependent routines - MS DOS Generic
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1998 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  *
  30.  * Notes:
  31.  *     - This file should contain the cross section of functions useful
  32.  *       in both DOS and Windows ports of pico.
  33.  *
  34.  */
  35.  
  36.  
  37. /*
  38.  * picosigs - Install any handlers for the signals we're interested
  39.  *          in catching.
  40.  */
  41. picosigs()
  42. {
  43.     /* no op */
  44. }
  45.  
  46.  
  47. /*
  48.  * Useful definitions...
  49.  */
  50. #ifdef    MOUSE
  51. static int mexist = 0;            /* is the mouse driver installed? */
  52. static int nbuttons;            /* number of buttons on the mouse */
  53. static unsigned mnoop;
  54. #endif
  55. static unsigned char okinfname[32] = {
  56.       0,    0,             /* ^@ - ^G, ^H - ^O  */
  57.       0,    0,            /* ^P - ^W, ^X - ^_  */
  58.       0x80, 0x17,        /* SP - ' ,  ( - /   */
  59.       0xff, 0xe4,        /*  0 - 7 ,  8 - ?   */
  60.       0x7f, 0xff,        /*  @ - G ,  H - O   */
  61.       0xff, 0xe9,        /*  P - W ,  X - _   */
  62.       0x7f, 0xff,        /*  ` - g ,  h - o   */
  63.       0xff, 0xf6,        /*  p - w ,  x - DEL */
  64.       0,    0,             /*  > DEL   */
  65.       0,    0,            /*  > DEL   */
  66.       0,    0,             /*  > DEL   */
  67.       0,    0,             /*  > DEL   */
  68.       0,    0             /*  > DEL   */
  69. };
  70.  
  71.  
  72. /*
  73.  * fallowc - returns TRUE if c is allowable in filenames, FALSE otw
  74.  */
  75. fallowc(c)
  76. int c;
  77. {
  78.     return(okinfname[c>>3] & 0x80>>(c&7));
  79. }
  80.  
  81.  
  82. #ifdef    MOUSE
  83. /*
  84.  * end_mouse - a no-op on DOS/Windows
  85.  */
  86. void
  87. end_mouse()
  88. {
  89. }
  90.  
  91.  
  92. /*
  93.  * mouseexist - function to let outsiders know if mouse is turned on
  94.  *              or not.
  95.  */
  96. mouseexist()
  97. {
  98.     return(mexist);
  99. }
  100. #endif    /* MOUSE */
  101.  
  102.  
  103. /*
  104.  * fexist - returns TRUE if the file exists, FALSE otherwise
  105.  */
  106. fexist(file, m, l)
  107. char  *file, *m;
  108. off_t *l;
  109. {
  110.     struct stat    sbuf;
  111.  
  112.     if(l != NULL)
  113.       *l = (off_t)0;
  114.  
  115.     if(stat(file, &sbuf) < 0){
  116.     if(errno == ENOENT)            /* File not found */
  117.       return(FIOFNF);
  118.     else
  119.       return(FIOERR);
  120.     }
  121.  
  122.     if(l != NULL)
  123.       *l = (off_t)sbuf.st_size;
  124.  
  125.     if(sbuf.st_mode & S_IFDIR)
  126.       return(FIODIR);
  127.     else if(*m == 't')                /* no links, just say yes */
  128.       return(FIOSUC);
  129.  
  130.     if(m[0] == 'r')                /* read access? */
  131.       return((S_IREAD & sbuf.st_mode) ? FIOSUC : FIONRD);
  132.     else if(m[0] == 'w')            /* write access? */
  133.       return((S_IWRITE & sbuf.st_mode) ? FIOSUC : FIONWT);
  134.     else if(m[0] == 'x')            /* execute access? */
  135.       return((S_IEXEC & sbuf.st_mode) ? FIOSUC : FIONEX);
  136.     return(FIOERR);                /* what? */
  137. }
  138.  
  139.  
  140. /*
  141.  * isdir - returns true if fn is a readable directory, false otherwise
  142.  *         silent on errors (we'll let someone else notice the problem;)).
  143.  */
  144. isdir(fn, l, d)
  145. char *fn;
  146. long *l;
  147. time_t *d;
  148. {
  149.     struct stat sbuf;
  150.  
  151.     if(l)
  152.       *l = 0;
  153.  
  154.     if(stat(fn, &sbuf) < 0)
  155.       return(0);
  156.  
  157.     if(l)
  158.       *l = sbuf.st_size;
  159.  
  160.     if(d)
  161.       *d = sbuf.st_mtime;
  162.  
  163.     return(sbuf.st_mode & S_IFDIR);
  164. }
  165.  
  166.  
  167. /*
  168.  * gethomedir - returns the users home directory
  169.  *              Note: home is malloc'd for life of pico
  170.  */
  171. char *gethomedir(l)
  172. int *l;
  173. {
  174.     static char *home = NULL;
  175.     static short hlen = 0;
  176.  
  177.     if(home == NULL){
  178.     char buf[NLINE];
  179.     sprintf(buf, "%c:\\", _getdrive() + 'A' - 1);
  180.     hlen = strlen(buf);
  181.     if((home=(char *)malloc(((size_t)hlen + 1) * sizeof(char))) == NULL){
  182.         emlwrite("Problem allocating space for home dir", NULL);
  183.         return(0);
  184.     }
  185.     strcpy(home, buf);
  186.     }
  187.  
  188.     if(l)
  189.       *l = hlen;
  190.  
  191.     return(home);
  192. }
  193.  
  194.  
  195. /*
  196.  * homeless - returns true if given file does not reside in the current
  197.  *            user's home directory tree. 
  198.  */
  199. homeless(f)
  200. char *f;
  201. {
  202.     char *home;
  203.     int   len;
  204.  
  205.     home = gethomedir(&len);
  206.     return(strncmp(home, f, len));
  207. }
  208.  
  209.  
  210. /*
  211.  * errstr - return system error string corresponding to given errno
  212.  *          Note: strerror() is not provided on all systems, so it's 
  213.  *          done here once and for all.
  214.  */
  215. char *errstr(err)
  216. int err;
  217. {
  218.     return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL);
  219. }
  220.  
  221.  
  222. /*
  223.  * getfnames - return all file names in the given directory in a single 
  224.  *             malloc'd string.  n contains the number of names
  225.  */
  226. char *getfnames(dn, pat, n, e)
  227. char *dn, *pat, *e;
  228. int  *n;
  229. {
  230.     int status;
  231.     long l;
  232.     char *names, *np, *p;
  233.     char buf[NLINE];
  234.     struct stat sbuf;
  235. #ifdef    WIN32
  236.     struct _finddata_t dbuf;
  237.     long   findrv;
  238. #else
  239.     struct find_t dbuf;                    /* opened directory */
  240. #endif
  241.  
  242.     *n = 0;
  243.  
  244.     if(stat(dn, &sbuf) < 0){
  245.     if(e)
  246.       sprintf(e, "\007Dir \"%s\": %s", dn, strerror(errno));
  247.  
  248.     return(NULL);
  249.     } 
  250.     else{
  251.     l = sbuf.st_size;
  252.     if(!(sbuf.st_mode & S_IFDIR)){
  253.         if(e)
  254.           sprintf(e, "\007Not a directory: \"%s\"", dn);
  255.  
  256.         return(NULL);
  257.     }
  258.     }
  259.  
  260.     if((names=(char *)malloc(sizeof(char)*3072)) == NULL){
  261.     if(e)
  262.     sprintf(e, "\007Can't malloc space for file names", NULL);
  263.  
  264.     return(NULL);
  265.     }
  266.  
  267.     np = names;
  268.  
  269.     strcpy(buf, dn);
  270.     sprintf(buf, "%s%s%s*%s%s", dn,
  271.         (dn[strlen(dn)-1] == '\\') ? "" : "\\",
  272.         (pat && *pat) ? pat : "",
  273.         (pat && *pat && strchr(pat, '.')) ? "" : ".",
  274.         (pat && *pat && strchr(pat, '.')) ? "" : "*");
  275. #ifdef    WIN32
  276.     if((findrv = _findfirst(buf, &dbuf)) < 0){
  277. #else
  278.     if(_dos_findfirst(buf, _A_NORMAL|_A_SUBDIR, &dbuf) != 0){
  279. #endif
  280.     if(e)
  281.       sprintf(e, "Can't find first file in \"%s\"", dn);
  282.  
  283.     free((char *) names);
  284.     return(NULL);
  285.     }
  286.  
  287.     do{
  288.     (*n)++;
  289.     p = dbuf.name;
  290.     while((*np++ = *p++) != '\0')
  291.       ;
  292.     }
  293. #ifdef    WIN32
  294.     while(_findnext(findrv, &dbuf) == 0);
  295.     _findclose(findrv);
  296. #else
  297.     while(_dos_findnext(&dbuf) == 0);
  298. #endif
  299.  
  300.     return(names);
  301. }
  302.  
  303.  
  304. /*
  305.  * fioperr - given the error number and file name, display error
  306.  */
  307. void
  308. fioperr(e, f)
  309. int  e;
  310. char *f;
  311. {
  312.     switch(e){
  313.       case FIOFNF:                /* File not found */
  314.     emlwrite("\007File \"%s\" not found", f);
  315.     break;
  316.       case FIOEOF:                /* end of file */
  317.     emlwrite("\007End of file \"%s\" reached", f);
  318.     break;
  319.       case FIOLNG:                /* name too long */
  320.     emlwrite("\007File name \"%s\" too long", f);
  321.     break;
  322.       case FIODIR:                /* file is a directory */
  323.     emlwrite("\007File \"%s\" is a directory", f);
  324.     break;
  325.       case FIONWT:
  326.     emlwrite("\007Write permission denied: %s", f);
  327.     break;
  328.       case FIONRD:
  329.     emlwrite("\007Read permission denied: %s", f);
  330.     break;
  331.       case FIONEX:
  332.     emlwrite("\007Execute permission denied: %s", f);
  333.     break;
  334.       default:
  335.     emlwrite("\007File I/O error: %s", f);
  336.     }
  337. }
  338.  
  339.  
  340. /*
  341.  * pfnexpand - pico's function to expand the given file name if there is 
  342.  *           a leading '~'
  343.  */
  344. char *pfnexpand(fn, len)
  345. char *fn;
  346. int  len;
  347. {
  348.     register char *x, *y, *z;
  349.     char *home = NULL;
  350.     char name[_MAX_PATH];
  351.     
  352.     if(*fn == '~' && *(x = fn + 1) == '\\') {
  353.     if(!(home = (char *) getenv("HOME"))
  354.        && getenv("HOMEDRIVE") && getenv("HOMEPATH"))
  355.       sprintf(home = name, "%s%s",
  356.           (char *) getenv("HOMEDRIVE"), (char *) getenv("HOMEPATH"));
  357.  
  358.     if(home){
  359.         /* make room for expanded path */
  360.         for(z = x + strlen(x), y = fn + strlen(x) + strlen(home);
  361.         z >= x;
  362.         *y-- = *z--)
  363.           ;
  364.  
  365.         /* and insert the expanded address */
  366.         for(x = fn, y = home; *y != '\0'; *x++ = *y++)
  367.           ;
  368.     }
  369.     }
  370.  
  371.     return(fn);
  372. }
  373.  
  374.  
  375. /*
  376.  * fixpath - make the given pathname into an absolute path
  377.  */
  378. fixpath(name, len)
  379. char *name;
  380. int  len;
  381. {
  382.     char file[_MAX_PATH];
  383.     int  dr;
  384.  
  385.     if(!len)
  386.       return(0);
  387.     
  388.     /* return the full path of given file, so drive spec? */
  389.     if(name[1] == ':' && isalpha((unsigned char) name[0])){
  390.     if(name[2] != '\\'){                  /* including path? */
  391.         dr = toupper((unsigned char)name[0]) - 'A' + 1;
  392.         if(_getdcwd(dr, file, _MAX_PATH) != NULL){
  393.         if(file[strlen(file)-1] != '\\')
  394.           strcat(file, "\\");
  395.  
  396.         strcat(file, &name[2]);        /* add file name */
  397.         }
  398.         else
  399.           return(0);
  400.     }
  401.     else
  402.       return(1);        /* fully qualified with drive and path! */
  403.     }
  404.     else if(name[0] == '\\') {            /* no drive spec! */
  405.     sprintf(file, "%c:%s", _getdrive()+'A'-1, name);
  406.     }
  407.     else{
  408.     if(Pmaster && !(gmode & MDCURDIR))
  409.       strcpy(file, ((gmode & MDTREE) || opertree[0])
  410.               ? opertree : gethomedir(NULL));
  411.     else if(!_getcwd(file, _MAX_PATH))    /* no qualification */
  412.       return(0);
  413.  
  414.     if(*name){                /* if name, append it */
  415.         if(*file && file[strlen(file)-1] != '\\')
  416.           strcat(file, "\\");
  417.  
  418.         strcat(file, name);
  419.     }
  420.     }
  421.  
  422.     strncpy(name, file, len);            /* copy back to real buffer */
  423.     name[len-1] = '\0';                /* tie off just in case */
  424.     return(1);
  425. }
  426.  
  427.  
  428. /*
  429.  * compresspath - given a base path and an additional directory, collapse
  430.  *                ".." and "." elements and return absolute path (appending
  431.  *                base if necessary).  
  432.  *
  433.  *                returns  1 if OK, 
  434.  *                         0 if there's a problem
  435.  *                         new path, by side effect, if things went OK
  436.  */
  437. compresspath(base, path, len)
  438. char *base, *path;
  439. int  len;
  440. {
  441.     register int i;
  442.     int  depth = 0;
  443.     char *p;
  444.     char *stack[32];
  445.     char  pathbuf[NLINE];
  446.  
  447. #define PUSHD(X)  (stack[depth++] = X)
  448. #define POPD()    ((depth > 0) ? stack[--depth] : "")
  449.  
  450.     strcpy(pathbuf, path);
  451.     fixpath(pathbuf, len);
  452.  
  453.     p = pathbuf;
  454.     for(i=0; pathbuf[i] != '\0'; i++){        /* pass thru path name */
  455.     if(pathbuf[i] == C_FILESEP){
  456.         if(p != pathbuf)
  457.           PUSHD(p);                /* push dir entry */
  458.         p = &pathbuf[i+1];            /* advance p */
  459.         pathbuf[i] = '\0';            /* cap old p off */
  460.         continue;
  461.     }
  462.  
  463.     if(pathbuf[i] == '.'){            /* special cases! */
  464.         if(pathbuf[i+1] == '.'            /* parent */
  465.            && (pathbuf[i+2] == C_FILESEP || pathbuf[i+2] == '\0')){
  466.         if(!strcmp(POPD(),""))        /* bad news! */
  467.           return(0);
  468.  
  469.         i += 2;
  470.         p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
  471.         }
  472.         else if(pathbuf[i+1] == C_FILESEP || pathbuf[i+1] == '\0'){
  473.         i++;
  474.         p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
  475.         }
  476.     }
  477.     }
  478.  
  479.     if(*p != '\0')
  480.       PUSHD(p);                    /* get last element */
  481.  
  482.     path[0] = '\0';
  483.     for(i = 0; i < depth; i++){
  484.     strcat(path, S_FILESEP);
  485.     strcat(path, stack[i]);
  486.     }
  487.  
  488.     return(1);                    /* everything's ok */
  489. }
  490.  
  491.  
  492. /*
  493.  * tmpname - return a temporary file name in the given buffer, the filename
  494.  * is in the directory dir unless dir is NULL
  495.  */
  496. void
  497. tmpname(dir, name)
  498. char *dir;
  499. char *name;
  500. {
  501.     char tmp[_MAX_PATH];
  502.  
  503.     if(!((dir && *dir) || (dir = getenv("TEMP"))))
  504.       if(!(getcwd(dir = tmp, _MAX_PATH)
  505.        && fexist(dir, "w", (off_t *) NULL) == FIOSUC))
  506.     dir = "c:\\";
  507.       
  508.     sprintf(name, "%s.txt", tempnam(dir, "ae"));
  509. }
  510.  
  511.  
  512. /*
  513.  * Take a file name, and from it
  514.  * fabricate a buffer name. This routine knows
  515.  * about the syntax of file names on the target system.
  516.  * I suppose that this information could be put in
  517.  * a better place than a line of code.
  518.  */
  519. void
  520. makename(bname, fname)
  521. char    bname[];
  522. char    fname[];
  523. {
  524.         register char   *cp1;
  525.         register char   *cp2;
  526.  
  527.         cp1 = &fname[0];
  528.         while (*cp1 != 0)
  529.                 ++cp1;
  530.  
  531.         while (cp1!=&fname[0] && cp1[-1]!='\\')
  532.                 --cp1;
  533.         cp2 = &bname[0];
  534.         while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
  535.                 *cp2++ = *cp1++;
  536.         *cp2 = 0;
  537. }
  538.  
  539.  
  540. /*
  541.  * copy - copy contents of file 'a' into a file named 'b'.  Return error
  542.  *        if either isn't accessible or is a directory
  543.  */
  544. copy(a, b)
  545. char *a, *b;
  546. {
  547.     int    in, out, n, rv = 0;
  548.     char   *cb;
  549.     struct stat tsb, fsb;
  550.  
  551.     if(stat(a, &fsb) < 0){        /* get source file info */
  552.     emlwrite("Can't Copy: %s", errstr(errno));
  553.     return(-1);
  554.     }
  555.  
  556.     if(!(fsb.st_mode&S_IREAD)){        /* can we read it? */
  557.     emlwrite("\007Read permission denied: %s", a);
  558.     return(-1);
  559.     }
  560.  
  561.     if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */
  562.     emlwrite("\007Can't copy: %s is a directory", a);
  563.     return(-1);
  564.     }
  565.  
  566.     if(stat(b, &tsb) < 0){        /* get dest file's mode */
  567.     switch(errno){
  568.       case ENOENT:
  569.         break;            /* these are OK */
  570.       default:
  571.         emlwrite("\007Can't Copy: %s", errstr(errno));
  572.         return(-1);
  573.     }
  574.     }
  575.     else{
  576.     if(!(tsb.st_mode&S_IWRITE)){    /* can we write it? */
  577.         emlwrite("\007Write permission denied: %s", b);
  578.         return(-1);
  579.     }
  580.  
  581.     if((tsb.st_mode&S_IFMT) == S_IFDIR){    /* is it directory? */
  582.         emlwrite("\007Can't copy: %s is a directory", b);
  583.         return(-1);
  584.     }
  585.  
  586.     if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){
  587.         emlwrite("\007Identical files.  File not copied", NULL);
  588.         return(-1);
  589.     }
  590.     }
  591.  
  592.     if((in = open(a, _O_RDONLY)) < 0){
  593.     emlwrite("Copy Failed: %s", errstr(errno));
  594.     return(-1);
  595.     }
  596.  
  597.     if((out=creat(b, fsb.st_mode&0xfff)) < 0){
  598.     emlwrite("Can't Copy: %s", errstr(errno));
  599.     close(in);
  600.     return(-1);
  601.     }
  602.  
  603.     if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){
  604.     emlwrite("Can't allocate space for copy buffer!", NULL);
  605.     close(in);
  606.     close(out);
  607.     return(-1);
  608.     }
  609.  
  610.     while(1){                /* do the copy */
  611.     if((n = read(in, cb, NLINE)) < 0){
  612.         emlwrite("Can't Read Copy: %s", errstr(errno));
  613.         rv = -1;
  614.         break;            /* get out now */
  615.     }
  616.  
  617.     if(n == 0)            /* done! */
  618.       break;
  619.  
  620.     if(write(out, cb, n) != n){
  621.         emlwrite("Can't Write Copy: %s", errstr(errno));
  622.         rv = -1;
  623.         break;
  624.     }
  625.     }
  626.  
  627.     free(cb);
  628.     close(in);
  629.     close(out);
  630.     return(rv);
  631. }
  632.  
  633.  
  634. /*
  635.  * Open a file for writing. Return TRUE if all is well, and FALSE on error
  636.  * (cannot create).
  637.  */
  638. ffwopen(fn, readonly)
  639. char    *fn;
  640. int     readonly;
  641. {
  642.     extern FIOINFO g_pico_fio;
  643.  
  644.     g_pico_fio.flags = FIOINFO_WRITE;
  645.     if ((g_pico_fio.fp = fopen(g_pico_fio.name = fn, "w")) == NULL) {
  646.         emlwrite("Cannot open file for writing", NULL);
  647.         return (FIOERR);
  648.     }
  649.  
  650. #ifdef    MODE_READONLY
  651.     if(readonly)
  652.       chmod(fn, MODE_READONLY);        /* fix access rights */
  653. #endif
  654.  
  655.     return (FIOSUC);
  656. }
  657.  
  658.  
  659. /*
  660.  * Close a file. Should look at the status in all systems.
  661.  */
  662. ffclose()
  663. {
  664.     extern FIOINFO g_pico_fio;
  665.  
  666.     if (fclose(g_pico_fio.fp) != FALSE) {
  667.         emlwrite("Error closing file", NULL);
  668.         return(FIOERR);
  669.     }
  670.  
  671.     return(FIOSUC);
  672. }
  673.  
  674.  
  675. /*
  676.  * ffelbowroom - make sure the destination's got enough room to receive
  677.  *         what we're about to write...
  678.  */
  679. ffelbowroom()
  680. {
  681.     return(TRUE);
  682. }
  683.  
  684.  
  685. /*
  686.  * worthit - generic sort of test to roughly gage usefulness of using 
  687.  *           optimized scrolling.
  688.  *
  689.  * note:
  690.  *    returns the line on the screen, l, that the dot is currently on
  691.  */
  692. worthit(l)
  693. int *l;
  694. {
  695.     int i;            /* l is current line */
  696.     unsigned below;        /* below is avg # of ch/line under . */
  697.  
  698.     *l = doton(&i, &below);
  699.     below = (i > 0) ? below/(unsigned)i : 0;
  700.  
  701.     return(below > 3);
  702. }
  703.  
  704.  
  705. /*
  706.  * o_insert - optimize screen insert of char c
  707.  */
  708. o_insert(c)
  709.     int c;
  710. {
  711.     return(0);
  712. }
  713.  
  714.  
  715. /*
  716.  * o_delete - optimized character deletion
  717.  */
  718. o_delete()
  719. {
  720.     return(0);
  721. }
  722.  
  723.  
  724. /*
  725.  * pico_new_mail - just checks mtime and atime of mail file and notifies user 
  726.  *               if it's possible that they have new mail.
  727.  */
  728. pico_new_mail()
  729. {
  730.     return(0);
  731. }
  732.  
  733.  
  734.  
  735. /*
  736.  * time_to_check - checks the current time against the last time called 
  737.  *                 and returns true if the elapsed time is > timeo
  738.  */
  739. time_to_check()
  740. {
  741.     static time_t lasttime = 0L;
  742.  
  743.     if(!timeo)
  744.       return(FALSE);
  745.  
  746.     if(time((long *) 0) - lasttime > (time_t)timeo){
  747.     lasttime = time((long *) 0);
  748.     return(TRUE);
  749.     }
  750.     else
  751.       return(FALSE);
  752. }
  753.  
  754.  
  755. /*
  756.  * sstrcasecmp - compare two pointers to strings case independently
  757.  */
  758. sstrcasecmp(s1, s2)
  759. QcompType *s1, *s2;
  760. {
  761.     return((*pcollator)(*(char **)s1, *(char **)s2));
  762. }
  763.  
  764.  
  765. int
  766. strucmp(o, r)
  767.     char *o, *r;
  768. {
  769.     return(o ? (r ? stricmp(o, r) : 1) : (r ? -1 : 0));
  770. }
  771.  
  772.  
  773. int
  774. struncmp(o, r, n)
  775.     char *o, *r;
  776.     int   n;
  777. {
  778.     return(o ? (r ? strnicmp(o, r, n) : 1) : (r ? -1 : 0));
  779. }
  780.  
  781.  
  782. /*
  783.  * chkptinit -- initialize anything we need to support composer
  784.  *        checkpointing
  785.  */
  786. chkptinit(file, n)
  787.     char *file;
  788.     int   n;
  789. {
  790.     if(!file[0]){
  791.     long gmode_save = gmode;
  792.  
  793.     if(gmode&MDCURDIR)
  794.       gmode &= ~MDCURDIR;  /* so fixpath will use home dir */
  795.  
  796.     strcpy(file, "#picoTM0.txt");
  797.     fixpath(file, NLINE);
  798.     gmode = gmode_save;
  799.     }
  800.     else{
  801.     int l = strlen(file);
  802.  
  803.     if(file[l-1] != '\\'){
  804.         file[l++] = '\\';
  805.         file[l]   = '\0';
  806.     }
  807.  
  808.     strcpy(file + l, "#picoTM0.txt");
  809.     }
  810.  
  811.     if(fexist(file, "r", (off_t *)NULL) == FIOSUC){ /* does file exist? */
  812.     char copy[NLINE];
  813.  
  814.     strcpy(copy, "#picoTM1.txt");
  815.     fixpath(copy, NLINE);
  816.     rename(file, copy);  /* save so we don't overwrite it */
  817.     }
  818.  
  819.     unlink(file);
  820. }
  821.  
  822.  
  823. void
  824. set_collation()
  825. {
  826.     char *status = NULL;
  827.     extern int collator();  /* strcoll isn't declared on all systems */
  828.  
  829.     pcollator = strucmp;
  830.  
  831. #ifdef LC_COLLATE
  832.     /*
  833.      * This may not have the desired effect, if collator is not
  834.      * defined to be strcoll in os.h and strcmp and friends
  835.      * don't know about locales. If your system does have strcoll
  836.      * but we haven't defined collator to be strcoll in os.h, let us know.
  837.      */
  838.     status = setlocale(LC_COLLATE, "");
  839.  
  840.     /*
  841.      * If there is an error or if the locale is the "C" locale, then we
  842.      * don't want to use strcoll because in the default "C" locale strcoll
  843.      * uses strcmp ordering and we want strucmp ordering.
  844.      *
  845.      * The test for "C" isn't really correct, since status does not have to
  846.      * be "C" even if we're in the "C" locale. But this works on some systems.
  847.      */
  848.     if(status && !(status[0] == 'C' && status[1] == '\0'))
  849.       pcollator = collator;
  850. #endif
  851. #ifdef LC_CTYPE
  852.     (void)setlocale(LC_CTYPE, "");
  853. #endif
  854. }
  855.  
  856.  
  857. /*
  858.  * sleep the given number of microseconds
  859.  */
  860. ssleep(s)
  861.     clock_t s;
  862. {
  863.     s += clock();
  864.     while(s > clock())
  865.       ;
  866. }
  867.  
  868.  
  869. /*
  870.  * sleep the given number of seconds
  871.  */
  872. sleep(t)
  873.     int t;
  874. {
  875.     time_t out = (time_t)t + time((long *) 0);
  876.     while(out > time((long *) 0))
  877.       ;
  878. }
  879.  
  880.  
  881. /*
  882.  * map the ftruncate call into DOS' chsize
  883.  */
  884. int
  885. truncate(file, size)
  886.     char *file;
  887.     long  size;
  888. {
  889.     int fd, rv = -1;
  890.  
  891.     if((fd = open(file, O_RDWR | O_CREAT | S_IREAD | S_IWRITE)) != -1){
  892.     if(chsize(fd, size) == 0)
  893.       rv = 0;
  894.  
  895.     close(fd);
  896.     }
  897.  
  898.     return(rv);
  899. }
  900.