S_ISCHR, S_ISFIFO, O_NONBLOCK, O_NOCTTY

Melissa O'Neill oneill@cs.sfu.ca
Sat Feb 6 13:16:00 GMT 1999


Zack wrote:
> Well, even if NEXTSTEP has S_IFIFO, we can't rely on all 4.x (x<4)
> derivatives to have it.  So we do need to detect sockets some other
> way.

Right...

> I've appended a partial patch to do the detection.  It has portability
> problems.  One is easy: we need an S_ISSOCK() default definition in
> system.h now.  Could you please add that to your patch?  If there is no
> S_IFSOCK, don't define it at all (note the conditionals in my patch).
> Also, I've assumed that if S_ISSOCK or S_IFSOCK is available in
> <sys/stat.h> then fstat() on a socket will use those values.

I don't think that is a correct assumption.  I think in a BSD 4.2 system,
stat on a Unix domain socket in the filesystem will set S_ISSOCK, but
fstat on a file descriptor will fail. Remember that `BUGS' line I quoted
from my NEXTSTEP system. While it doesn't appear to apply any more, I'd
guess that it used to apply in BSD 4.2 (and earlier?).  The quote was:

    BUGS
	  Applying fstat to a socket (and thus to a pipe) returns a
	  zeroed buffer, except for the blocksize field, and a unique
	  device and inode number.

I'd probably just use something like:

      else if (S_ISFIFO (st.st_mode)
    #ifdef S_ISSOCK
		|| S_ISSOCK (st.st_mode)
    #endif
    #ifdef SOCKET_FSTAT_BUG
    		|| (st.st_mode == 0 && st.st_size == 0 && st.st_nlink == 0)
		  /* socket/pipe in BSD 4.x (x < 4) */
    #endif
		|| (S_ISCHR (st.st_mode) && isatty (fd)))

An alternative would be to have a definition of S_ISSOCK that looks
like this:

    /* Test if something is a socket.  */
    #ifndef S_ISSOCK
    # ifdef S_IFSOCK
    #  ifdef SOCKET_FSTAT_BUG
    #   define S_ISSOCK(m) ((m) == 0 || ((m) & S_IFMT) == S_IFSOCK)
    #  else
    #   define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
    #  endif
    # else
    #   define S_ISSOCK(m) 0
    # endif
    #endif

but the above is only checking st.mode, rather than checking a few
other fields for being zero as well.

I think either of the above is probably a better solution than trying
to use shutdown, given what you said about shutdown's not being in some
early BSDs.  (Of course, how you'd get to set SOCKET_FSTAT_BUG is an
exercise for the reader.)

    Melissa.

P.S. Enclosed is my patch, with S_ISSOCK added (but without SOCKET_FSTAT_BUG).

Enc.

--- system.h.orig	Wed Feb  3 23:16:17 1999
+++ system.h	Sat Feb  6 13:10:19 1999
@@ -410,8 +410,41 @@
 #ifndef S_ISDIR
 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
 #endif

+/* Test if something is a character special file.  */
+#ifndef S_ISCHR
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+
+/* Test if something is a socket.  */
+#ifndef S_ISSOCK
+# ifdef S_IFSOCK
+#   define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+#   define S_ISSOCK(m) 0
+# endif
+#endif
+
+/* Test if something is a FIFO.  */
+#ifndef S_ISFIFO
+# ifdef S_IFIFO
+#  define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+#  define S_ISFIFO(m) 0
+# endif
+#endif
+
+/* Approximate O_NONBLOCK.  */
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+/* Approximate O_NOCTTY.  */
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
 /* Get libiberty declarations. */
 #include "libiberty.h"

 #if defined (ANSI_PROTOTYPES)


More information about the Gcc-patches mailing list