diff -ru screen-4.0.2.orig/attacher.c screen-4.0.2/attacher.c --- screen-4.0.2.orig/attacher.c 2003-09-08 23:24:48.000000000 +0900 +++ screen-4.0.2/attacher.c 2004-12-01 15:34:27.009755200 +0900 @@ -274,7 +274,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); @@ -420,7 +420,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-4.0.2.orig/config.h.in screen-4.0.2/config.h.in --- screen-4.0.2.orig/config.h.in 2003-12-05 22:59:39.000000000 +0900 +++ screen-4.0.2/config.h.in 2004-12-01 15:34:27.009755200 +0900 @@ -184,6 +184,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-4.0.2.orig/display.c screen-4.0.2/display.c --- screen-4.0.2.orig/display.c 2003-12-05 22:45:41.000000000 +0900 +++ screen-4.0.2/display.c 2004-12-01 15:34:27.019769600 +0900 @@ -94,6 +94,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-4.0.2.orig/extern.h screen-4.0.2/extern.h --- screen-4.0.2.orig/extern.h 2003-08-22 21:27:57.000000000 +0900 +++ screen-4.0.2/extern.h 2004-12-01 15:34:27.019769600 +0900 @@ -490,3 +490,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-4.0.2.orig/misc.c screen-4.0.2/misc.c --- screen-4.0.2.orig/misc.c 2003-12-05 22:45:41.000000000 +0900 +++ screen-4.0.2/misc.c 2004-12-01 15:34:27.019769600 +0900 @@ -613,7 +613,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); @@ -632,6 +632,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-4.0.2.orig/pty.c screen-4.0.2/pty.c --- screen-4.0.2.orig/pty.c 2003-09-08 23:26:18.000000000 +0900 +++ screen-4.0.2/pty.c 2004-12-01 15:34:27.029784000 +0900 @@ -34,7 +34,7 @@ #endif /* for solaris 2.1, Unixware (SVR4.2) and possibly others */ -#ifdef HAVE_SVR4_PTYS +#if defined(HAVE_SVR4_PTYS) && !defined(__CYGWIN__) # include #endif diff -ru screen-4.0.2.orig/resize.c screen-4.0.2/resize.c --- screen-4.0.2.orig/resize.c 2003-09-08 23:26:31.000000000 +0900 +++ screen-4.0.2/resize.c 2004-12-01 15:35:15.158990400 +0900 @@ -993,7 +993,11 @@ /* signal new size to window */ #ifdef TIOCSWINSZ +#ifndef __CYGWIN__ /* really needed? */ 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-4.0.2.orig/screen.c screen-4.0.2/screen.c --- screen-4.0.2.orig/screen.c 2003-09-08 23:26:41.000000000 +0900 +++ screen-4.0.2/screen.c 2004-12-01 15:34:27.029784000 +0900 @@ -890,7 +890,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."); @@ -1023,8 +1023,10 @@ if ((int)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; @@ -1070,7 +1072,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."); @@ -1418,7 +1420,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()) @@ -1637,7 +1639,7 @@ xseteuid(real_uid); xsetegid(real_gid); #endif - (void) unlink(SockPath); + (void) screen_unlink(SockPath); #ifdef USE_SETEUID xseteuid(eff_uid); xsetegid(eff_gid); @@ -1675,7 +1677,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-4.0.2.orig/socket.c screen-4.0.2/socket.c --- screen-4.0.2.orig/socket.c 2003-09-08 23:26:50.000000000 +0900 +++ screen-4.0.2/socket.c 2004-12-01 15:34:27.039798400 +0900 @@ -81,6 +81,12 @@ # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0)) #endif +#ifdef O_BINARY +# define MY_O_BINARY O_BINARY +#else +# define MY_O_BINARY 0 +#endif + /* * Socket directory manager @@ -181,7 +187,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; @@ -260,7 +266,7 @@ sent->mode = -1; if (wipeflag) { - if (unlink(SockPath) == 0) + if (screen_unlink(SockPath) == 0) { sent->mode = -2; nwipe++; @@ -416,7 +422,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 ((int)st.st_uid != real_uid) Panic(0, "Unfortunatelly you are not its owner."); @@ -427,13 +433,13 @@ /* 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) + if ((s = open(SockPath, O_RDWR | O_NONBLOCK | MY_O_BINARY, 0)) < 0) # else - if ((s = open(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) + if ((s = open(SockPath, O_RDONLY | O_NONBLOCK | MY_O_BINARY, 0)) < 0) # endif Panic(errno, "open fifo %s", SockPath); xseteuid(eff_uid); @@ -442,15 +448,15 @@ # 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); # ifdef BROKEN_PIPE - if ((s = secopen(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0) + if ((s = secopen(SockPath, O_RDWR | O_NONBLOCK | MY_O_BINARY, 0)) < 0) # else - if ((s = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) + if ((s = secopen(SockPath, O_RDONLY | O_NONBLOCK | MY_O_BINARY, 0)) < 0) # endif Panic(errno, "open fifo %s", SockPath); return s; @@ -464,7 +470,7 @@ { register int s = 0; - if ((s = secopen(SockPath, O_WRONLY | O_NONBLOCK, 0)) >= 0) + if ((s = secopen(SockPath, O_WRONLY | O_NONBLOCK | MY_O_BINARY, 0)) >= 0) { (void) fcntl(s, F_SETFL, 0); return s; @@ -508,7 +514,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."); @@ -523,7 +529,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 @@ -534,7 +540,7 @@ close(f); } #else - chmod(SockPath, SOCKMODE); + screen_chmod(SockPath, SOCKMODE); # ifndef USE_SETEUID chown(SockPath, real_uid, real_gid); # endif @@ -823,7 +829,8 @@ # ifndef BROKEN_PIPE /* Reopen pipe to prevent EOFs at the select() call */ close(ServerSocket); - if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) + if ((ServerSocket = secopen(SockPath, + O_RDONLY | O_NONBLOCK | MY_O_BINARY, 0)) < 0) Panic(errno, "reopen fifo %s", SockPath); evdeq(&serv_read); serv_read.fd = ServerSocket; @@ -908,7 +915,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); @@ -1045,7 +1056,7 @@ int x; sap = (struct sockaddr_un *)sapp; - if (stat(sap->sun_path, &st)) + if (screen_stat(sap->sun_path, &st)) return -1; chmod(sap->sun_path, 0); x = connect(s, (struct sockaddr *) sap, len); @@ -1067,7 +1078,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 @@ -1090,11 +1101,11 @@ if ((int)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; @@ -1424,3 +1435,157 @@ 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. + */ + +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-4.0.2.orig/utmp.c screen-4.0.2/utmp.c --- screen-4.0.2.orig/utmp.c 2003-09-08 23:27:17.000000000 +0900 +++ screen-4.0.2/utmp.c 2004-12-01 15:34:27.039798400 +0900 @@ -89,7 +89,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 @@ -589,7 +589,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 @@ -858,7 +858,7 @@ } # endif /* BUGGYGETLOGIN */ -#if defined(linux) && defined(GETUTENT) +#if (defined(linux) || defined(__CYGWIN__)) && defined(GETUTENT) # undef pututline /* aargh, linux' pututline returns void! */