home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / screen-3.5 / part03 / fileio.c < prev    next >
C/C++ Source or Header  |  1993-07-25  |  16KB  |  750 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: fileio.c,v 1.2 1993/06/23 17:46:30 jnweiger Exp $ FAU")
  25.  
  26.  
  27. #include <sys/types.h>
  28. #ifndef sgi
  29. # include <sys/file.h>
  30. #endif /* sgi */
  31. #include <sys/stat.h>
  32. #include <fcntl.h>
  33.  
  34. #include <signal.h>
  35.  
  36. #include "config.h" 
  37. #include "screen.h"
  38. #include "extern.h"
  39.  
  40. #ifdef NETHACK
  41. extern nethackflag;
  42. #endif
  43.  
  44. extern struct display *display;
  45. extern struct win *fore;
  46. extern int real_uid, eff_uid;
  47. extern int real_gid, eff_gid;
  48. extern char *extra_incap, *extra_outcap;
  49. extern char *home, *RcFileName;
  50. extern char SockPath[], *SockNamePtr;
  51. #ifdef COPY_PASTE
  52. extern char *BufferFile;
  53. #endif
  54. extern int hardcopy_append;
  55. extern char *hardcopydir;
  56.  
  57. static char *CatExtra __P((char *, char *));
  58.  
  59.  
  60. static FILE *fp = NULL;
  61. char *rc_name;
  62.  
  63. static char *
  64. CatExtra(str1, str2)
  65. register char *str1, *str2;
  66. {
  67.   register char *cp;
  68.   register int len1, len2, add_colon;
  69.  
  70.   len1 = strlen(str1);
  71.   if (len1 == 0)
  72.     return(str2);
  73.   add_colon = (str1[len1 - 1] != ':');
  74.   if (str2)
  75.     {
  76.       len2 = strlen(str2);
  77.       if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL)
  78.     Panic(0, strnomem);
  79.       bcopy(cp, cp + len1 + add_colon, len2 + 1);
  80.     }
  81.   else
  82.     {
  83.       if (len1 == 0)
  84.     return 0;
  85.       if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL)
  86.     Panic(0, strnomem);
  87.       cp[len1 + add_colon] = '\0'; 
  88.     }
  89.   bcopy(str1, cp, len1);
  90.   if (add_colon)
  91.     cp[len1] = ':';
  92.  
  93.   return cp;
  94. }
  95.  
  96. static char *
  97. findrcfile(rcfile)
  98. char *rcfile;
  99. {
  100.   static char buf[256];
  101.   char *rc, *p;
  102.  
  103.   if (rcfile)
  104.     {
  105.       rc = SaveStr(rcfile);
  106.       debug1("findrcfile: you specified '%s'\n", rcfile);
  107.     }
  108.   else
  109.     {
  110.       debug("findrcfile: you specified nothing...\n");
  111.       if ((p = getenv("ISCREENRC")) != NULL && *p != '\0')
  112.     {
  113.       debug1("  ... but $ISCREENRC has: '%s'\n", p);
  114.       rc = SaveStr(p);
  115.     }
  116.       else if ((p = getenv("SCREENRC")) != NULL && *p != '\0')
  117.     {
  118.       debug1("  ... but $SCREENRC has: '%s'\n", p);
  119.       rc = SaveStr(p);
  120.     }
  121.       else
  122.     {
  123.       debug("  ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n");
  124.       if (strlen(home) > 244)
  125.         Panic(0, "Rc: home too large");
  126.       sprintf(buf, "%s/.iscreenrc", home);
  127.           if (access(buf, R_OK))
  128.         sprintf(buf, "%s/.screenrc", home);
  129.       rc = SaveStr(buf);
  130.     }
  131.     }
  132.   return rc;
  133. }
  134.  
  135. /*
  136.  * this will be called twice:
  137.  * 1) rcfilename = "/etc/screenrc"
  138.  * 2) rcfilename = RcFileName
  139.  */
  140. void
  141. StartRc(rcfilename)
  142. char *rcfilename;
  143. {
  144.   register int argc, len;
  145.   register char *p, *cp;
  146.   char buf[256];
  147.   char *args[MAXARGS];
  148.  
  149.   rc_name = findrcfile(rcfilename);
  150.  
  151.   if ((fp = secfopen(rc_name, "r")) == NULL)
  152.     {
  153.       if (RcFileName && strcmp(RcFileName, rc_name) == 0)
  154.     {
  155.           /*
  156.            * User explicitly gave us that name,
  157.            * this is the only case, where we get angry, if we can't read
  158.            * the file.
  159.            */
  160.       debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name, rcfilename);
  161.           Panic(0, "Unable to open \"%s\".", rc_name);
  162.       /* NOTREACHED */
  163.     }
  164.       debug1("StartRc: '%s' no good. ignored\n", rc_name);
  165.       Free(rc_name);
  166.       rc_name = "";
  167.       return;
  168.     }
  169.   while (fgets(buf, sizeof buf, fp) != NULL)
  170.     {
  171.       if ((p = rindex(buf, '\n')) != NULL)
  172.     *p = '\0';
  173.       if ((argc = Parse(buf, args)) == 0)
  174.     continue;
  175.       if (strcmp(args[0], "echo") == 0)
  176.     {
  177.       if (!display)
  178.         continue;
  179.       if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3)
  180.         {
  181.           Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name);
  182.           continue;
  183.         }
  184.       AddStr(args[argc - 1]);
  185.       if (argc != 3)
  186.         {
  187.           AddStr("\r\n");
  188.           Flush();
  189.         }
  190.     }
  191.       else if (strcmp(args[0], "sleep") == 0)
  192.     {
  193.       if (!display)
  194.         continue;
  195.       debug("sleeeeeeep\n");
  196.       if (argc != 2)
  197.         {
  198.           Msg(0, "%s: sleep: one numeric argument expected.", rc_name);
  199.           continue;
  200.         }
  201.       DisplaySleep(atoi(args[1]));
  202.     }
  203. #ifdef TERMINFO
  204.       else if (strcmp(args[0], "terminfo") == 0)
  205. #else
  206.       else if (strcmp(args[0], "termcap") == 0)
  207. #endif
  208.     {
  209.       if (!display)
  210.         continue;
  211.       if (argc < 3 || argc > 4)
  212.         {
  213.           Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]);
  214.           continue;
  215.         }
  216.       for (p = args[1]; p && *p; p = cp)
  217.         {
  218.           if ((cp = index(p, '|')) != 0)
  219.         *cp++ = '\0';
  220.           len = strlen(p);
  221.           if (p[len - 1] == '*')
  222.         {
  223.           if (!(len - 1) || !strncmp(p, d_termname, len - 1))
  224.             break;
  225.         }
  226.           else if (!strcmp(p, d_termname))
  227.         break;
  228.         }
  229.       if (!(p && *p))
  230.         continue;
  231.       extra_incap = CatExtra(args[2], extra_incap);
  232.       if (argc == 4)
  233.         extra_outcap = CatExtra(args[3], extra_outcap);
  234.     }
  235.     }
  236.   fclose(fp);
  237.   Free(rc_name);
  238.   rc_name = "";
  239. }
  240.  
  241. void
  242. FinishRc(rcfilename)
  243. char *rcfilename;
  244. {
  245.   char buf[256];
  246.  
  247.   rc_name = findrcfile(rcfilename);
  248.  
  249.   if ((fp = secfopen(rc_name, "r")) == NULL)
  250.     {
  251.       if (RcFileName && strcmp(RcFileName, rc_name) == 0)
  252.     {
  253.           /*
  254.         * User explicitly gave us that name, 
  255.        * this is the only case, where we get angry, if we can't read
  256.        * the file.
  257.        */
  258.         debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name, rcfilename);
  259.           Panic(0, "Unable to open \"%s\".", rc_name);
  260.       /* NOTREACHED */
  261.     }
  262.       debug1("FinishRc: '%s' no good. ignored\n", rc_name);
  263.       Free(rc_name);
  264.       rc_name = "";
  265.       return;
  266.     }
  267.  
  268.   debug("finishrc is going...\n");
  269.   while (fgets(buf, sizeof buf, fp) != NULL)
  270.     {
  271.       RcLine(buf);
  272.     }
  273.   (void) fclose(fp);
  274.   Free(rc_name);
  275.   rc_name = "";
  276. }
  277.  
  278. /*
  279.  *    "$HOST blafoo"       -> "localhost blafoo"
  280.  *    "${HOST}blafoo"          -> "localhostblafoo"
  281.  *    "\$HOST blafoo"     -> "$HOST blafoo"
  282.  *    "\\$HOST blafoo"    -> "\localhost blafoo"
  283.  *    "'$HOST ${HOST}'"    -> "'$HOST ${HOST}'" 
  284.  *    "'\$HOST'"           -> "'\$HOST'"
  285.  *    "\'$HOST' $HOST"       -> "'localhost' $HOST"
  286.  *
  287.  *    "$:termcapname:"    -> "termcapvalue"
  288.  *    "$:terminfoname:"    -> "termcapvalue"
  289.  *
  290.  *    "\101"            -> "A"
  291.  */
  292. char *
  293. expand_vars(ss)
  294. char *ss;
  295. {
  296.   static char ebuf[2048];
  297.   register int esize = 2047, vtype, quofl = 0;
  298.   register char *e = ebuf;
  299.   register char *s = ss;
  300.   register char *v;
  301.   char xbuf[11];
  302.  
  303.   while (*s && *s != '\0' && *s != '\n' && esize > 0)
  304.     {
  305.       if (*s == '\'')
  306.     quofl ^= 1;
  307.       if (*s == '$' && !quofl)
  308.     {
  309.       char *p, c;
  310.  
  311.       p = ++s;
  312.       switch (*s)
  313.         {
  314.         case '{':
  315.           p = ++s;
  316.           while (*p != '}')
  317.             if (*p++ == '\0')
  318.               return ss;
  319.           vtype = 0;        /* env var */
  320.           break;
  321.         case ':':
  322.           p = ++s;
  323.           while (*p != ':')
  324.         if (*p++ == '\0')
  325.           return ss;
  326.           vtype = 1;        /* termcap string */
  327.           break;
  328.         default:
  329.           while (*p != ' ' && *p != '\0' && *p != '\n')
  330.         p++;
  331.           vtype = 0;        /* env var */
  332.         }
  333.       c = *p;
  334.       debug1("exp: c='%c'\n", c);
  335.       *p = '\0';
  336.       if (vtype == 0)
  337.         {
  338.           v = xbuf;
  339.           if (strcmp(s, "TERM") == 0)
  340.         v = display ? d_termname : "unknown";
  341.           else if (strcmp(s, "COLUMNS") == 0)
  342.         sprintf(xbuf, "%d", display ? d_width : -1);
  343.           else if (strcmp(s, "LINES") == 0)
  344.         sprintf(xbuf, "%d", display ? d_height : -1);
  345.           else
  346.         v = getenv(s);
  347.         }
  348.       else
  349.         v = gettermcapstring(s);
  350.       if (v)
  351.         {
  352.           debug2("exp: $'%s'='%s'\n", s, v);
  353.           while (*v && esize-- > 0)
  354.             *e++ = *v++;
  355.         }
  356.       else 
  357.         debug1("exp: '%s' not env\n", s);  /* {-: */
  358.       if ((*p = c) == '}' || c == ':')
  359.         p++;
  360.       s = p;
  361.     }
  362.       else
  363.     {
  364.       /*
  365.        * \$, \\$, \\, \\\, \012 are reduced here, 
  366.        * d_other sequences starting whith \ are passed through.
  367.        */
  368.       if (s[0] == '\\' && !quofl)
  369.         {
  370.           if (s[1] >= '0' && s[1] <= '7')
  371.         {
  372.           int i;
  373.  
  374.           s++;
  375.           i = *s - '0';
  376.           s++;
  377.           if (*s >= '0' && *s <= '7')
  378.             {
  379.               i = i * 8 + *s - '0';
  380.               s++;
  381.               if (*s >= '0' && *s <= '7')
  382.             {
  383.               i = i * 8 + *s - '0';
  384.               s++;
  385.             }
  386.             }
  387.           debug2("expandvars: octal coded character %o (%d)\n", i, i);
  388.           *e++ = i;
  389.         }
  390.           else
  391.         {
  392.           if (s[1] == '$' || 
  393.               (s[1] == '\\' && s[2] == '$') ||
  394.               s[1] == '\'' || 
  395.               (s[1] == '\\' && s[2] == '\''))
  396.             s++;
  397.         }
  398.         }
  399.       *e++ = *s++;
  400.       esize--;
  401.     }
  402.     }
  403.   if (esize <= 0)
  404.     Msg(0, "expand_vars: buffer overflow\n");
  405.   *e = '\0';
  406.   return ebuf;
  407. }
  408.  
  409. void
  410. RcLine(ubuf)
  411. char *ubuf;
  412. {
  413.   char *args[MAXARGS], *buf;
  414.   struct action act;
  415.  
  416.   buf = expand_vars(ubuf); 
  417.   if (Parse(buf, args) <= 0)
  418.     return;
  419.   if ((act.nr = FindCommnr(*args)) == RC_ILLEGAL)
  420.     {
  421.       Msg(0, "%s: unknown command '%s'", rc_name, *args);
  422.       return;
  423.     }
  424.   act.args = args + 1;
  425.   DoAction(&act, -1);
  426. }
  427.  
  428.  
  429. void
  430. WriteFile(dump)
  431. int dump;
  432. {
  433.   /* dump==0:    create .termcap,
  434.    * dump==1:    hardcopy,
  435.    * #ifdef COPY_PASTE
  436.    * dump==2:    BUFFERFILE
  437.    * #endif COPY_PASTE 
  438.    */
  439.   register int i, j, k;
  440.   register char *p;
  441.   register FILE *f;
  442.   char fn[1024];
  443.   char *mode = "w";
  444.  
  445.   switch (dump)
  446.     {
  447.     case DUMP_TERMCAP:
  448.       i = SockNamePtr - SockPath;
  449.       strncpy(fn, SockPath, i);
  450.       strcpy(fn + i, ".termcap");
  451.       break;
  452.     case DUMP_HARDCOPY:
  453.       if (hardcopydir)
  454.     sprintf(fn, "%s/hardcopy.%d", hardcopydir, fore->w_number);
  455.       else
  456.         sprintf(fn, "hardcopy.%d", fore->w_number);
  457.       if (hardcopy_append && !access(fn, W_OK))
  458.     mode = "a";
  459.       break;
  460. #ifdef COPY_PASTE
  461.     case DUMP_EXCHANGE:
  462.       sprintf(fn, "%s", BufferFile);
  463.       umask(0);
  464.       break;
  465. #endif
  466.     }
  467.  
  468.   debug2("WriteFile(%d) %s\n", dump, fn);
  469.   if (UserContext() > 0)
  470.     {
  471.       debug("Writefile: usercontext\n");
  472.       if ((f = fopen(fn, mode)) == NULL)
  473.     {
  474.       debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode);
  475.       UserReturn(0);
  476.     }
  477.       else
  478.     {
  479.       switch (dump)
  480.         {
  481.         case DUMP_HARDCOPY:
  482.           if (*mode == 'a')
  483.         {
  484.           putc('>', f);
  485.           for (j = d_width - 2; j > 0; j--)
  486.             putc('=', f);
  487.           fputs("<\n", f);
  488.         }
  489.           for (i = 0; i < d_height; i++)
  490.         {
  491.           p = fore->w_image[i];
  492.           for (k = d_width - 1; k >= 0 && p[k] == ' '; k--)
  493.             ;
  494.           for (j = 0; j <= k; j++)
  495.             putc(p[j], f);
  496.           putc('\n', f);
  497.         }
  498.           break;
  499.         case DUMP_TERMCAP:
  500.           if ((p = index(MakeTermcap(fore->w_aflag), '=')) != NULL)
  501.         {
  502.           fputs(++p, f);
  503.           putc('\n', f);
  504.         }
  505.           break;
  506. #ifdef COPY_PASTE
  507.         case DUMP_EXCHANGE:
  508.           p = d_copybuffer;
  509.           for (i = 0; i < d_copylen; i++)
  510.         putc(*p++, f);
  511.           break;
  512. #endif
  513.         }
  514.       (void) fclose(f);
  515.       UserReturn(1);
  516.     }
  517.     }
  518.   if (UserStatus() <= 0)
  519.     Msg(0, "Cannot open \"%s\"", fn);
  520.   else
  521.     {
  522.       switch (dump)
  523.     {
  524.     case DUMP_TERMCAP:
  525.       Msg(0, "Termcap entry written to \"%s\".", fn);
  526.       break;
  527.     case DUMP_HARDCOPY:
  528.       Msg(0, "Screen image %s to \"%s\".",
  529.           (*mode == 'a') ? "appended" : "written", fn);
  530.       break;
  531. #ifdef COPY_PASTE
  532.     case DUMP_EXCHANGE:
  533.       Msg(0, "Copybuffer written to \"%s\".", fn);
  534. #endif
  535.     }
  536.     }
  537. }
  538.  
  539. #ifdef COPY_PASTE
  540.  
  541. void
  542. ReadFile()
  543. {
  544.   int i, l, size;
  545.   char fn[1024], c;
  546.   struct stat stb;
  547.  
  548.   sprintf(fn, "%s", BufferFile);
  549.   debug1("ReadFile(%s)\n", fn);
  550.   if ((i = secopen(fn, O_RDONLY, 0)) < 0)
  551.     {
  552.       Msg(errno, "no %s -- no slurp", fn);
  553.       return;
  554.     }
  555.   if (fstat(i, &stb))
  556.     {
  557.       Msg(errno, "no good %s -- no slurp", fn);
  558.       close(i);
  559.       return;
  560.     }
  561.   size = stb.st_size;
  562.   if (d_copybuffer)
  563.     free(d_copybuffer);
  564.   d_copylen = 0;
  565.   if ((d_copybuffer = malloc(size)) == NULL)
  566.     {
  567.       close(i);
  568.       Msg(0, strnomem);
  569.       return;
  570.     }
  571.   errno = 0;
  572.   if ((l = read(i, d_copybuffer, size)) != size)
  573.     {
  574.       d_copylen = (l > 0) ? l : 0;
  575. #ifdef NETHACK
  576.       if (nethackflag)
  577.         Msg(errno, "You choke on your food: %d bytes", d_copylen);
  578.       else
  579. #endif
  580.       Msg(errno, "Got only %d bytes from %s", d_copylen, fn);
  581.       close(i);
  582.       return;
  583.     }
  584.   d_copylen = l;
  585.   if (read(i, &c, 1) > 0)
  586.     Msg(0, "Slurped only %d characters into buffer - try again", d_copylen);
  587.   else
  588.     Msg(0, "Slurped %d characters into buffer", d_copylen);
  589.   close(i);
  590.   return;
  591. }
  592.  
  593. void
  594. KillBuffers()
  595. {
  596.   char fn[1024];
  597.   sprintf(fn, "%s", BufferFile);
  598.   errno = 0;
  599. #ifndef NOREUID
  600.   setreuid(eff_uid, real_uid);
  601.   setregid(eff_gid, real_gid);
  602. #else
  603.   if (access(fn, W_OK) == -1)
  604.     {
  605.       Msg(errno, "%s not removed", fn);
  606.       return;
  607.     }
  608. #endif
  609.   unlink(fn);
  610.   Msg(errno, "%s removed", fn);
  611. #ifndef NOREUID
  612.   setreuid(real_uid, eff_uid);
  613.   setregid(real_gid, eff_gid);
  614. #endif
  615. }
  616. #endif    /* COPY_PASTE */
  617.  
  618.  
  619. /*
  620.  * (Almost) secure open and fopen...
  621.  */
  622.  
  623. FILE *
  624. secfopen(name, mode)
  625. char *name;
  626. char *mode;
  627. {
  628.   FILE *fi;
  629. #ifdef NOREUID
  630.   int flags, fd;
  631. #endif
  632.  
  633.   debug2("secfopen(%s, %s)\n", name, mode);
  634. #ifndef NOREUID
  635.   setreuid(eff_uid, real_uid);
  636.   setregid(eff_gid, real_gid);
  637.   fi = fopen(name, mode);
  638.   setreuid(real_uid, eff_uid);
  639.   setregid(real_gid, eff_gid);
  640.   return fi;
  641. #else
  642.   if (eff_uid == real_uid)
  643.     return(fopen(name, mode));
  644.   if (mode[0] && mode[1] == '+')
  645.     flags = O_RDWR;
  646.   else
  647.     flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY;
  648.   if (mode[0] == 'w')
  649.     flags |= O_CREAT | O_TRUNC;
  650.   else if (mode[0] == 'a')
  651.     flags |= O_CREAT | O_APPEND;
  652.   else if (mode[0] != 'r')
  653.     {
  654.       errno = EINVAL;
  655.       return(0);
  656.     }
  657.   if ((fd = secopen(name, flags, 0666)) < 0)
  658.     return(0);
  659.   if ((fi = fdopen(fd, mode)) == 0)
  660.     {
  661.       close(fd);
  662.       return(0);
  663.     }
  664.   return(fi);
  665. #endif
  666. }
  667.  
  668.  
  669. int
  670. secopen(name, flags, mode)
  671. char *name;
  672. int flags;
  673. int mode;
  674. {
  675.   int fd;
  676. #ifdef NOREUID
  677.   int q;
  678.   struct stat stb;
  679. #endif
  680.  
  681.   debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode);
  682. #ifndef NOREUID
  683.   setreuid(eff_uid, real_uid);
  684.   setregid(eff_gid, real_gid);
  685.   fd = open(name, flags, mode);
  686.   setreuid(real_uid, eff_uid);
  687.   setregid(real_gid, eff_gid);
  688.   return fd;
  689. #else
  690.   if (eff_uid == real_uid)
  691.     return(open(name, flags, mode));
  692.   /* Truncation/creation is done in UserContext */
  693.   if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK)))
  694.     {
  695.       if (UserContext() > 0)
  696.     {
  697.           if ((fd = open(name, flags, mode)) >= 0)
  698.         {
  699.           close(fd);
  700.           UserReturn(0);
  701.             }
  702.       if (errno == 0)
  703.         errno = EACCES;
  704.       UserReturn(errno);
  705.     }
  706.       if (q = UserStatus())
  707.     {
  708.       if (q > 0)
  709.         errno = q;
  710.           return(-1);
  711.     }
  712.     }
  713.   if (access(name, F_OK))
  714.     return(-1);
  715.   if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0)
  716.     return(-1);
  717.   debug("open successful\n");
  718.   if (fstat(fd, &stb))
  719.     {
  720.       close(fd);
  721.       return(-1);
  722.     }
  723.   debug("fstat successful\n");
  724.   if (stb.st_uid != real_uid)
  725.     {
  726.       switch (flags & (O_RDONLY | O_WRONLY | O_RDWR))
  727.         {
  728.     case O_RDONLY:
  729.       q = 0004;
  730.       break;
  731.     case O_WRONLY:
  732.       q = 0002;
  733.       break;
  734.     default:
  735.       q = 0006;
  736.       break;
  737.         }
  738.       if ((stb.st_mode & q) != q)
  739.     {
  740.           debug("secopen: permission denied\n");
  741.       close(fd);
  742.       errno = EACCES;
  743.       return(-1);
  744.     }
  745.     }
  746.   debug1("secopen ok - returning %d\n", fd);
  747.   return(fd);
  748. #endif
  749. }
  750.