Gmane
From: AIDA Shinra <shinra <at> j10n.org>
Subject: Patch for recent Cygwin
Newsgroups: gmane.comp.gnu.screen
Date: 2003-08-12 13:56:18 GMT (5 years, 46 weeks, 5 days, 5 hours and 15 minutes ago)
Recent versions of Cygwin does not save permissions to UNIX-domain
sockets. I wrote a workaround code. It also add support of FAT32
without CYGWIN=ntea.

diff -ru screen-3.9.15.orig/attacher.c screen-3.9.15/attacher.c
--- screen-3.9.15.orig/attacher.c	2002-08-23 04:21:53.000000000 +0900
+++ screen-3.9.15/attacher.c	2003-05-16 13:00:32.000000000 +0900
@@ -277,7 +277,7 @@
     }
   debug1("Attach decided, it is '%s'\n", SockPath);
   debug1("Attach found MasterPid == %d\n", MasterPid);
-  if (stat(SockPath, &st) == -1)
+  if (screen_stat(SockPath, &st) == -1)
     Panic(errno, "stat %s", SockPath);
   if ((st.st_mode & 0600) != 0600)
     Panic(0, "Socket is in wrong mode (%03o)", (int)st.st_mode);
@@ -423,7 +423,7 @@
   debug("AttacherFinit();\n");
   signal(SIGHUP, SIG_IGN);
   /* Check if signal comes from backend */
-  if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600)
+  if (screen_stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600)
     {
       debug("Detaching backend!\n");
       bzero((char *) &m, sizeof(m));
diff -ru screen-3.9.15.orig/config.h.in screen-3.9.15/config.h.in
--- screen-3.9.15.orig/config.h.in	2003-03-13 20:19:53.000000000 +0900
+++ screen-3.9.15/config.h.in	2003-05-16 13:01:24.000000000 +0900
@@ -180,6 +180,15 @@
 #undef RXVT_OSC
 #undef COLORS256

+#ifdef __CYGWIN__
+# define CYGWIN_FILEMODE
+#else
+# undef CYGWIN_FILEMODE
+#endif
+#ifdef CYGWIN_FILEMODE
+# undef MULTIUSER
+#endif
+

 /*
  * If you have a braille display you should define HAVE_BRAILLE.
diff -ru screen-3.9.15.orig/display.c screen-3.9.15/display.c
--- screen-3.9.15.orig/display.c	2003-02-24 20:53:35.000000000 +0900
+++ screen-3.9.15/display.c	2003-05-16 13:00:32.000000000 +0900
@@ -75,6 +75,9 @@
 /*
  * tputs needs this to calculate the padding
  */
+#if defined(__CYGWIN__) && !defined(NCURSES_STATIC)
+__declspec(dllimport)
+#endif
 #ifndef NEED_OSPEED
 extern
 #endif /* NEED_OSPEED */
diff -ru screen-3.9.15.orig/extern.h screen-3.9.15/extern.h
--- screen-3.9.15.orig/extern.h	2003-02-25 02:01:17.000000000 +0900
+++ screen-3.9.15/extern.h	2003-05-16 13:02:33.000000000 +0900
@@ -479,3 +479,19 @@
 # endif
 #endif
 extern int   EncodeChar __P((char *, int, int, int *));
+
+#ifdef CYGWIN_FILEMODE
+extern int screen_stat __P((char *, struct stat *));
+extern int screen_chmod __P((char *, mode_t));
+# ifdef NAMEDPIPE
+extern int screen_mkfifo __P((char *, mode_t));
+# endif
+extern int screen_unlink __P((char *));
+#else /* CYGWIN_FILEMODE */
+# define screen_stat(path, st) stat(path, st)
+# define screen_chmod(path, mode) chmod(path, mode)
+# ifdef NAMEDPIPE
+#  define screen_mkfifo(path, mode) mkfifo(path, mode)
+# endif
+# define screen_unlink(path) unlink(path)
+#endif /* CYGWIN_FILEMODE */
diff -ru screen-3.9.15.orig/misc.c screen-3.9.15/misc.c
--- screen-3.9.15.orig/misc.c	2003-02-22 05:30:57.000000000 +0900
+++ screen-3.9.15/misc.c	2003-05-16 13:00:32.000000000 +0900
@@ -642,7 +642,7 @@
    */
 # endif /* NEEDSETENV */
 #else /* USESETENV */
-# if defined(linux) || defined(__convex__) || (BSD >= 199103)
+# if defined(linux) || defined(__convex__) || (BSD >= 199103) || defined(__CYGWIN__)
   setenv(var, value, 1);
 # else
   setenv(var, value);
@@ -811,6 +811,9 @@
 int (*outc) __P((int));
 {
   int pad;
+#if defined(__CYGWIN__) && !defined(NCURSES_STATIC)
+__declspec(dllimport)
+#endif
   extern short ospeed;
   static short osp2pad[] = {
     0,2000,1333,909,743,666,500,333,166,83,55,41,20,10,5,2,1,1
diff -ru screen-3.9.15.orig/pty.c screen-3.9.15/pty.c
--- screen-3.9.15.orig/pty.c	2003-02-14 22:44:20.000000000 +0900
+++ screen-3.9.15/pty.c	2003-04-25 16:55:13.000000000 +0900
@@ -37,7 +37,7 @@
 #endif

 /* for solaris 2.1, Unixware (SVR4.2) and possibly others */
-#ifdef HAVE_SVR4_PTYS
+#if defined(HAVE_SVR4_PTYS) && !defined(__CYGWIN__)
 # include <sys/stropts.h>
 #endif

diff -ru screen-3.9.15.orig/resize.c screen-3.9.15/resize.c
--- screen-3.9.15.orig/resize.c	2002-11-09 01:31:51.000000000 +0900
+++ screen-3.9.15/resize.c	2003-05-12 13:22:51.000000000 +0900
@@ -991,7 +991,11 @@

   /* signal new size to window */
 #ifdef TIOCSWINSZ
+#ifndef __CYGWIN__
   if (wi && (p->w_width != wi || p->w_height != he) && p->w_ptyfd >= 0 && p->w_pid)
+#else
+  if (wi && (p->w_width != wi || p->w_height != he) && p->w_ptyfd >= 0)
+#endif
     {
       glwz.ws_col = wi;
       glwz.ws_row = he;
diff -ru screen-3.9.15.orig/screen.c screen-3.9.15/screen.c
--- screen-3.9.15.orig/screen.c	2003-02-25 02:03:47.000000000 +0900
+++ screen-3.9.15/screen.c	2003-05-16 15:01:29.000000000 +0900
@@ -886,7 +886,7 @@
   if (!detached && !lsflag && !cmdflag && !(dflag && !mflag && !rflag && !xflag))
     {
       /* ttyname implies isatty */
-      if (!(attach_tty = ttyname(0)))
+      if (!(attach_tty = strdup(ttyname(0))))
         Panic(0, "Must be connected to a terminal.");
       if (strlen(attach_tty) >= MAXPATHLEN)
 	Panic(0, "TtyName too long - sorry.");
@@ -1019,8 +1019,10 @@
       if (st.st_uid != real_uid)
 	Panic(0, "You are not the owner of %s.", SockPath);
     }
+#ifndef CYGWIN_FILEMODE
   if ((st.st_mode & 0777) != 0700)
     Panic(0, "Directory %s must have mode 700.", SockPath);
+#endif
   if (SockMatch && index(SockMatch, '/'))
     Panic(0, "Bad session name '%s'", SockMatch);
   SockName = SockPath + strlen(SockPath) + 1;
@@ -1066,7 +1068,7 @@
       char *sty = 0;

       /* attach_tty is not mandatory */
-      if ((attach_tty = ttyname(0)) == 0)
+      if ((attach_tty = strdup(ttyname(0))) == 0)
         attach_tty = "";
       if (strlen(attach_tty) >= MAXPATHLEN)
 	Panic(0, "TtyName too long - sorry.");
@@ -1414,7 +1416,7 @@
       signal(SIGCHLD, SigChld);
 #endif
     }
-  if (stat(SockPath, &st) == -1)
+  if (screen_stat(SockPath, &st) == -1)
     {
       debug1("SigChldHandler: Yuck! cannot stat '%s'\n", SockPath);
       if (!RecoverSocket())
@@ -1633,7 +1635,7 @@
       xseteuid(real_uid);
       xsetegid(real_gid);
 #endif
-      (void) unlink(SockPath);
+      (void) screen_unlink(SockPath);
 #ifdef USE_SETEUID
       xseteuid(eff_uid);
       xsetegid(eff_gid);
@@ -1671,7 +1673,7 @@
       debug1("we unlink(%s)\n", SockPath);
       setgid(real_gid);
       setuid(real_uid);
-      (void) unlink(SockPath);
+      (void) screen_unlink(SockPath);
     }
   exit(e);
 }
diff -ru screen-3.9.15.orig/socket.c screen-3.9.15/socket.c
--- screen-3.9.15.orig/socket.c	2003-02-25 02:08:34.000000000 +0900
+++ screen-3.9.15/socket.c	2003-05-16 13:00:36.000000000 +0900
@@ -184,7 +184,7 @@
       errno = 0;
       debug2("uid = %d, gid = %d\n", getuid(), getgid());
       debug2("euid = %d, egid = %d\n", geteuid(), getegid());
-      if (stat(SockPath, &st))
+      if (screen_stat(SockPath, &st))
 	{
 	  debug1("errno = %d\n", errno);
 	  continue;
@@ -263,7 +263,7 @@
 	  sent->mode = -1;
 	  if (wipeflag)
 	    {
-	      if (unlink(SockPath) == 0)
+	      if (screen_unlink(SockPath) == 0)
 		{
 		  sent->mode = -2;
 		  nwipe++;
@@ -419,7 +419,7 @@
 	  eexit(11);
 	}
       Msg(0, "There is already a screen running on %s.", Filename(SockPath));
-      if (stat(SockPath, &st) == -1)
+      if (screen_stat(SockPath, &st) == -1)
 	Panic(errno, "stat");
       if (st.st_uid != real_uid)
 	Panic(0, "Unfortunatelly you are not its owner.");
@@ -430,8 +430,8 @@
       /* NOTREACHED */
     }
 # ifdef USE_SETEUID
-  (void) unlink(SockPath);
-  if (mkfifo(SockPath, SOCKMODE))
+  (void) screen_unlink(SockPath);
+  if (screen_mkfifo(SockPath, SOCKMODE))
     Panic(0, "mkfifo %s failed", SockPath);
 #  ifdef BROKEN_PIPE
   if ((s = open(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0)
@@ -445,8 +445,8 @@
 # else /* !USE_SETEUID */
   if (UserContext() > 0)
     {
-      (void) unlink(SockPath);
-      UserReturn(mkfifo(SockPath, SOCKMODE));
+      (void) screen_unlink(SockPath);
+      UserReturn(screen_mkfifo(SockPath, SOCKMODE));
     }
   if (UserStatus())
     Panic(0, "mkfifo %s failed", SockPath);
@@ -511,7 +511,7 @@
 	  eexit(11);
 	}
       Msg(0, "There is already a screen running on %s.", Filename(SockPath));
-      if (stat(SockPath, &st) == -1)
+      if (screen_stat(SockPath, &st) == -1)
 	Panic(errno, "stat");
       if (st.st_uid != real_uid)
 	Panic(0, "Unfortunatelly you are not its owner.");
@@ -526,7 +526,7 @@
   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
     Panic(errno, "reopen socket");
 #endif
-  (void) unlink(SockPath);
+  (void) screen_unlink(SockPath);
   if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
     Panic(errno, "bind (%s)", SockPath);
 #ifdef SOCK_NOT_IN_FS
@@ -537,7 +537,7 @@
       close(f);
     }
 #else
-  chmod(SockPath, SOCKMODE);
+  screen_chmod(SockPath, SOCKMODE);
 # ifndef USE_SETEUID
   chown(SockPath, real_uid, real_gid);
 # endif
@@ -911,7 +911,11 @@
 	  Msg(0, "Attach attempt with bad pid(%d)!", m.m.attach.apid);
           break;
 	}
+#ifndef O_NOCTTY
       if ((i = secopen(m.m_tty, O_RDWR | O_NONBLOCK, 0)) < 0)
+#else /* O_NOCTTY */
+      if ((i = secopen(m.m_tty, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) < 0)
+#endif
 	{
 	  Msg(errno, "Attach: Could not open %s!", m.m_tty);
 	  Kill(m.m.attach.apid, SIG_BYE);
@@ -1070,7 +1074,7 @@
       if (UserContext() <= 0)
         return UserStatus();
     }
-  r = chmod(SockPath, SOCKMODE);
+  r = screen_chmod(SockPath, SOCKMODE);
   /* 
    * Sockets usually reside in the /tmp/ area, where sysadmin scripts
    * may be happy to remove old files. We manually prevent the socket
@@ -1093,11 +1097,11 @@
   if (geteuid() != real_uid)
     {
       if (UserContext() > 0)
-	UserReturn(unlink(SockPath));
+	UserReturn(screen_unlink(SockPath));
       (void)UserStatus();
     }
   else
-    (void) unlink(SockPath);
+    (void) screen_unlink(SockPath);

   if ((ServerSocket = MakeServerSocket()) < 0)
     return 0;
@@ -1423,3 +1427,160 @@
   EffectiveAclUser = 0;
 #endif
 }
+
+#ifdef CYGWIN_FILEMODE
+/* On cygwin (without ntea/ntsec), the mode of the UNIX domain
+ * socket is always either 755 or 655. Unfortunately, screen
+ * saves the socket state as the file mode.
+ *
+ * Therefore, we emulate the file mode, creating a special
+ * key file. This is ugly and possibly unsecure hack, but not
+ * critical on single-user system.
+ *
+ * If you found any bug, mail me:
+ *   AIDA Shinra <aida_s <at> mx12.freecom.ne.jp>
+ */
+
+static char *GetModeKeyPath __P((char *));
+static int CreateModeKeyFile __P((char *, mode_t));
+static int ReadModeKeyFile __P((char *, mode_t *));
+static char modekey_format[] = "$$ screen: socket mode=0%o $$\n";
+
+int
+screen_stat(path, st)
+char *path;
+struct stat *st;
+{
+  mode_t modetmp;
+
+  if (stat(SockPath, st))
+    return -1;
+  if (!ReadModeKeyFile(path, &modetmp))
+    st->st_mode = (st->st_mode & ~07777) | modetmp;
+  errno = 0;
+  return 0;
+}
+
+int
+screen_chmod(path, mode)
+char *path;
+mode_t mode;
+{
+  if (chmod(path, mode))
+    return -1;
+  CreateModeKeyFile(path, mode);
+  errno = 0;
+  return 0;
+}
+
+#ifdef NAMEDPIPE
+int
+screen_mkfifo(path, mode)
+char *path;
+mode_t mode;
+{
+  if (mkfifo(path, mode))
+    return -1;
+  CreateModeKeyFile(path, mode);
+  errno = 0;
+  return 0;
+}
+#endif
+
+int
+screen_unlink(path)
+char *path;
+{
+  char *modekey_path;
+  
+  if (unlink(path))
+    return -1;
+  if ((modekey_path = GetModeKeyPath(path)) == NULL)
+    return -1;
+  unlink(modekey_path);
+  free(modekey_path);
+  errno = 0;
+  return 0;
+}
+
+static char *
+GetModeKeyPath(path)
+char *path;
+{
+  char *keypath;
+  char *base;
+
+  keypath = malloc(strlen(path) + 7);
+  if (keypath == NULL) {
+    Panic (0, strnomem);
+    return NULL;
+  }
+  base = strrchr(path, '/');
+  if (base == NULL)
+    base = path;
+  else
+    base++;
+  strncpy(keypath, path, base-path);
+  sprintf(keypath+(base-path), ".%s.mode", base);
+  return keypath;
+}
+
+static int
+CreateModeKeyFile(path, mode)
+char *path;
+mode_t mode;
+{
+  int err = 0;
+  char *modekey_path;
+  FILE *keyfile;
+
+  if ((modekey_path = GetModeKeyPath(path)) == NULL)
+    return -1;
+  if ((keyfile = fopen(modekey_path, "w")) == NULL) {
+    err = errno;
+  } else {
+    errno = 0;
+    fprintf(keyfile, modekey_format, (unsigned int)mode);
+    if (errno)
+      err = errno;
+    if (fclose(keyfile))
+      err = errno;
+# ifndef USE_SETEUID
+    if (chown(modekey_path, getuid(), getgid()))
+      err = errno;
+# endif
+  }
+  free(modekey_path);
+  errno = err;
+  return (err) ? -1 : 0;
+}
+
+static int
+ReadModeKeyFile(path, modep)
+char *path;
+mode_t *modep;
+{
+  int err = 0;
+  char *modekey_path;
+  FILE *keyfile;
+  unsigned int mode_u;
+
+  if ((modekey_path = GetModeKeyPath(path)) == NULL)
+    return -1;
+
+  if ((keyfile = fopen(modekey_path, "r")) == NULL) {
+    err = errno;
+  } else {
+    if (fscanf(keyfile, modekey_format, &mode_u) != 1)
+      err=errno;
+    if (fclose(keyfile))
+      err=errno;
+  }
+  free(modekey_path);
+  errno = err;
+  if (err)
+    return -1;
+  *modep = (mode_t)mode_u;
+  return 0;
+}
+#endif /* CYGWIN_FILEMODE */
diff -ru screen-3.9.15.orig/utmp.c screen-3.9.15/utmp.c
--- screen-3.9.15.orig/utmp.c	2002-09-06 18:45:32.000000000 +0900
+++ screen-3.9.15/utmp.c	2003-05-16 15:13:08.000000000 +0900
@@ -93,7 +93,7 @@
 static int  initutmp __P((void));
 static void setutent __P((void));
 #endif
-#if defined(linux) && defined(GETUTENT)
+#if (defined(linux) || defined(__CYGWIN__)) && defined(GETUTENT)
 static struct utmp *xpututline __P((struct utmp *utmp));
 # define pututline xpututline
 #endif
@@ -593,7 +593,7 @@
 struct utmp *u;
 {
   u->ut_type = DEAD_PROCESS;
-#if !defined(linux) || defined(EMPTY)
+#if !defined(__CYGWIN__) && (!defined(linux) || defined(EMPTY))
   u->ut_exit.e_termination = 0;
   u->ut_exit.e_exit = 0;
 #endif
@@ -862,7 +862,7 @@
 }
 # endif /* BUGGYGETLOGIN */

-#if defined(linux) && defined(GETUTENT)
+#if (defined(linux) || defined(__CYGWIN__)) && defined(GETUTENT)
 # undef pututline

 /* aargh, linux' pututline returns void! */