2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
30 #include <sys/types.h>
33 #if !defined(NAMEDPIPE)
34 #include <sys/socket.h>
48 # define dirent direct
53 static int CheckPid
__P((int));
54 static void ExecCreate
__P((struct msg
*));
55 static void DoCommandMsg
__P((struct msg
*));
56 #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
57 # define connect sconnect /* _SEQUENT_ has braindamaged connect */
58 static int sconnect
__P((int, struct sockaddr
*, int));
60 static void FinishAttach
__P((struct msg
*));
61 static void FinishDetach
__P((struct msg
*));
62 static void AskPassword
__P((struct msg
*));
65 extern char *RcFileName
, *extra_incap
, *extra_outcap
;
66 extern int ServerSocket
, real_uid
, real_gid
, eff_uid
, eff_gid
;
67 extern int dflag
, iflag
, rflag
, lsflag
, quietflag
, wipeflag
, xflag
;
68 extern char *attach_tty
, *LoginName
, HostName
[];
69 extern struct display
*display
, *displays
;
70 extern struct win
*fore
, *wtab
[], *console_window
, *windows
;
71 extern struct layer
*flayer
;
72 extern struct layout
*layout_attach
, *layout_last
, layout_last_marker
;
73 extern struct NewWindow nwin_undef
;
78 extern char *getenv();
80 extern char SockPath
[];
81 extern struct event serv_read
;
83 extern struct comm comms
[];
86 # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0))
88 # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0))
93 * Socket directory manager
95 * fdp: pointer to store the first good socket.
96 * nfoundp: pointer to store the number of sockets found matching.
97 * notherp: pointer to store the number of sockets not matching.
98 * match: string to match socket name.
100 * The socket directory must be in SockPath!
101 * The global variables LoginName, multi, rflag, xflag, dflag,
102 * quietflag, SockPath are used.
104 * The first good socket is stored in fdp and its name is
105 * appended to SockPath.
106 * If none exists or fdp is NULL SockPath is not changed.
108 * Returns: number of good sockets.
113 FindSocket(fdp
, nfoundp
, notherp
, match
)
115 int *nfoundp
, *notherp
;
125 int firsts
= -1, sockfd
;
127 int nfound
= 0, ngood
= 0, ndead
= 0, nwipe
= 0, npriv
= 0;
134 } *slist
, **slisttail
, *sent
, *nsent
;
138 matchlen
= strlen(match
);
140 if (matchlen
> NAME_MAX
)
146 * SockPath contains the socket directory.
147 * At the end of FindSocket the socket name will be appended to it.
148 * Thus FindSocket() can only be called once!
150 sdirlen
= strlen(SockPath
);
157 if ((dirp
= opendir(SockPath
)) == 0)
158 Panic(errno
, "Cannot opendir %s", SockPath
);
162 while ((dp
= readdir(dirp
)))
166 debug1("- %s\n", name
);
167 if (*name
== 0 || *name
== '.' || strlen(name
) > 2*MAXSTR
)
172 /* if we don't want to match digits. Skip them */
173 if ((*match
<= '0' || *match
> '9') && (*n
> '0' && *n
<= '9'))
175 while (*n
>= '0' && *n
<= '9')
180 /* the tty prefix is optional */
181 if (strncmp(match
, "tty", 3) && strncmp(n
, "tty", 3) == 0)
183 if (strncmp(match
, n
, matchlen
))
185 cmatch
= (*(n
+ matchlen
) == 0);
186 debug1(" -> matched %s\n", match
);
188 sprintf(SockPath
+ sdirlen
, "/%s", name
);
190 debug1("stat %s\n", SockPath
);
192 debug2("uid = %d, gid = %d\n", getuid(), getgid());
193 debug2("euid = %d, egid = %d\n", geteuid(), getegid());
194 if (stat(SockPath
, &st
))
196 debug1("errno = %d\n", errno
);
200 #ifndef SOCK_NOT_IN_FS
203 debug("S_ISFIFO?\n");
204 if (!S_ISFIFO(st
.st_mode
))
209 debug("S_ISSOCK?\n");
210 if (!S_ISSOCK(st
.st_mode
))
216 debug2("st.st_uid = %d, real_uid = %d\n", st
.st_uid
, real_uid
);
217 if ((int)st
.st_uid
!= real_uid
)
219 mode
= (int)st
.st_mode
& 0777;
220 debug1(" has mode 0%03o\n", mode
);
222 if (multi
&& ((mode
& 0677) != 0601))
224 debug(" is not a MULTI-USER session");
225 if (strcmp(multi
, LoginName
))
227 debug(" and we are in a foreign directory.\n");
232 debug(", but it is our own session.\n");
236 debug(" store it.\n");
237 if ((sent
= (struct sent
*)malloc(sizeof(struct sent
))) == 0)
240 sent
->name
= SaveStr(name
);
243 slisttail
= &sent
->next
;
245 sockfd
= MakeClientSocket(0);
247 /* MakeClientSocket sets ids back to eff */
253 debug2(" MakeClientSocket failed, unreachable? %d %d\n",
256 #ifndef SOCKDIR_IS_LOCAL_TO_HOST
257 /* Unreachable - it is dead if we detect that it's local
258 * or we specified a match
260 n
= name
+ strlen(name
) - 1;
261 while (n
!= name
&& *n
!= '.')
263 if (matchlen
== 0 && !(*n
== '.' && n
[1] && strncmp(HostName
, n
+ 1, strlen(n
+ 1)) == 0))
265 npriv
++; /* a good socket that was not for us */
273 if (unlink(SockPath
) == 0)
283 /* Shall we connect ? */
284 debug2(" connecting: mode=%03o, rflag=%d, ", mode
, rflag
);
285 debug2("xflag=%d, dflag=%d ?\n", xflag
, dflag
);
288 * mode 600: socket is detached.
289 * mode 700: socket is attached.
290 * xflag implies rflag here.
292 * fail, when socket mode mode is not 600 or 700
293 * fail, when we want to detach w/o reattach, but it already is detached.
294 * fail, when we only want to attach, but mode 700 and not xflag.
295 * fail, if none of dflag, rflag, xflag is set.
297 if ((mode
!= 0700 && mode
!= 0600) ||
298 (dflag
&& !rflag
&& !xflag
&& mode
== 0600) ||
299 (!dflag
&& rflag
&& mode
== 0700 && !xflag
) ||
300 (!dflag
&& !rflag
&& !xflag
))
304 npriv
++; /* a good socket that was not for us */
310 if (fdp
&& (firsts
== -1 || (cmatch
&& nperfect
== 1)))
320 debug(" discarded.\n");
324 (void)closedir(dirp
);
325 if (!lsflag
&& nperfect
== 1)
327 if (nfound
&& (lsflag
|| ngood
!= 1) && !quietflag
)
332 Msg(0, nfound
> 1 ? "There are screens on:" : "There is a screen on:");
335 Msg(0, nfound
> 1 ? "There are several screens on:" : "There is a suitable screen on:");
338 Msg(0, "There are several suitable screens on:");
341 for (sent
= slist
; sent
; sent
= sent
->next
)
346 printf("\t%s\t(Attached)\n", sent
->name
);
349 printf("\t%s\t(Detached)\n", sent
->name
);
353 printf("\t%s\t(Multi, attached)\n", sent
->name
);
356 printf("\t%s\t(Multi, detached)\n", sent
->name
);
360 /* No trigraphs here! */
361 printf("\t%s\t(Dead ?%c?)\n", sent
->name
, '?');
364 printf("\t%s\t(Removed)\n", sent
->name
);
367 printf("\t%s\t(Remote or dead)\n", sent
->name
);
370 printf("\t%s\t(Private)\n", sent
->name
);
375 if (ndead
&& !quietflag
)
377 char *m
= "Remove dead screens with 'screen -wipe'.";
379 Msg(0, "%d socket%s wiped out.", nwipe
, nwipe
> 1 ? "s" : "");
381 Msg(0, m
, ndead
> 1 ? "s" : "", ndead
> 1 ? "" : "es"); /* other args for nethack */
385 sprintf(SockPath
+ sdirlen
, "/%s", firstn
);
389 SockPath
[sdirlen
] = 0;
390 for (sent
= slist
; sent
; sent
= nsent
)
403 *nfoundp
= nfound
- nwipe
;
410 ** Socket/pipe create routines
426 if ((s
= open(SockPath
, O_WRONLY
| O_NONBLOCK
)) >= 0)
428 debug("huii, my fifo already exists??\n");
431 Kill(D_userpid
, SIG_BYE
);
434 Msg(0, "There is already a screen running on %s.", Filename(SockPath
));
435 if (stat(SockPath
, &st
) == -1)
436 Panic(errno
, "stat");
437 if ((int)st
.st_uid
!= real_uid
)
438 Panic(0, "Unfortunatelly you are not its owner.");
439 if ((st
.st_mode
& 0700) == 0600)
440 Panic(0, "To resume it, use \"screen -r\"");
442 Panic(0, "It is not detached.");
446 (void) unlink(SockPath
);
447 if (mkfifo(SockPath
, SOCKMODE
))
448 Panic(0, "mkfifo %s failed", SockPath
);
450 if ((s
= open(SockPath
, O_RDWR
| O_NONBLOCK
, 0)) < 0)
452 if ((s
= open(SockPath
, O_RDONLY
| O_NONBLOCK
, 0)) < 0)
454 Panic(errno
, "open fifo %s", SockPath
);
458 # else /* !USE_SETEUID */
459 if (UserContext() > 0)
461 (void) unlink(SockPath
);
462 UserReturn(mkfifo(SockPath
, SOCKMODE
));
465 Panic(0, "mkfifo %s failed", SockPath
);
467 if ((s
= secopen(SockPath
, O_RDWR
| O_NONBLOCK
, 0)) < 0)
469 if ((s
= secopen(SockPath
, O_RDONLY
| O_NONBLOCK
, 0)) < 0)
471 Panic(errno
, "open fifo %s", SockPath
);
473 # endif /* !USE_SETEUID */
478 MakeClientSocket(err
)
483 if ((s
= secopen(SockPath
, O_WRONLY
| O_NONBLOCK
, 0)) >= 0)
485 (void) fcntl(s
, F_SETFL
, 0);
489 Msg(errno
, "%s", SockPath
);
490 debug2("MakeClientSocket() open %s failed (%d)\n", SockPath
, errno
);
495 #else /* NAMEDPIPE */
502 struct sockaddr_un a
;
505 if ((s
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1)
506 Panic(errno
, "socket");
507 a
.sun_family
= AF_UNIX
;
508 strncpy(a
.sun_path
, SockPath
, sizeof(a
.sun_path
));
509 a
.sun_path
[sizeof(a
.sun_path
) - 1] = 0;
514 if (connect(s
, (struct sockaddr
*) &a
, strlen(SockPath
) + 2) != -1)
516 debug("oooooh! socket already is alive!\n");
519 Kill(D_userpid
, SIG_BYE
);
521 * oh, well. nobody receives that return code. papa
526 Msg(0, "There is already a screen running on %s.", Filename(SockPath
));
527 if (stat(SockPath
, &st
) == -1)
528 Panic(errno
, "stat");
529 if (st
.st_uid
!= real_uid
)
530 Panic(0, "Unfortunatelly you are not its owner.");
531 if ((st
.st_mode
& 0700) == 0600)
532 Panic(0, "To resume it, use \"screen -r\"");
534 Panic(0, "It is not detached.");
537 #if defined(m88k) || defined(sysV68)
538 close(s
); /* we get bind: Invalid argument if this is not done */
539 if ((s
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1)
540 Panic(errno
, "reopen socket");
542 (void) unlink(SockPath
);
543 if (bind(s
, (struct sockaddr
*) & a
, strlen(SockPath
) + 2) == -1)
544 Panic(errno
, "bind (%s)", SockPath
);
545 #ifdef SOCK_NOT_IN_FS
548 if ((f
= secopen(SockPath
, O_RDWR
| O_CREAT
, SOCKMODE
)) < 0)
549 Panic(errno
, "shadow socket open");
553 chmod(SockPath
, SOCKMODE
);
555 chown(SockPath
, real_uid
, real_gid
);
557 #endif /* SOCK_NOT_IN_FS */
558 if (listen(s
, 5) == -1)
559 Panic(errno
, "listen");
561 fcntl(s
, F_SETOWN
, getpid());
562 debug1("Serversocket owned by %d\n", fcntl(s
, F_GETOWN
, 0));
563 # endif /* F_SETOWN */
572 MakeClientSocket(err
)
576 struct sockaddr_un a
;
578 if ((s
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1)
579 Panic(errno
, "socket");
580 a
.sun_family
= AF_UNIX
;
581 strncpy(a
.sun_path
, SockPath
, sizeof(a
.sun_path
));
582 a
.sun_path
[sizeof(a
.sun_path
) - 1] = 0;
587 if (access(SockPath
, W_OK
))
590 Msg(errno
, "%s", SockPath
);
591 debug2("MakeClientSocket: access(%s): %d.\n", SockPath
, errno
);
596 if (connect(s
, (struct sockaddr
*) &a
, strlen(SockPath
) + 2) == -1)
599 Msg(errno
, "%s: connect", SockPath
);
600 debug("MakeClientSocket: connect failed.\n");
610 #endif /* NAMEDPIPE */
615 ** Message send and receive routines
620 SendCreateMsg(sty
, nwin
)
622 struct NewWindow
*nwin
;
628 char **av
= nwin
->args
;
631 if (strlen(sty
) > NAME_MAX
)
634 if (strlen(sty
) > 2 * MAXSTR
- 1)
635 sty
[2 * MAXSTR
- 1] = 0;
636 sprintf(SockPath
+ strlen(SockPath
), "/%s", sty
);
637 if ((s
= MakeClientSocket(1)) == -1)
639 debug1("SendCreateMsg() to '%s'\n", SockPath
);
640 bzero((char *)&m
, sizeof(m
));
642 strncpy(m
.m_tty
, attach_tty
, sizeof(m
.m_tty
) - 1);
643 m
.m_tty
[sizeof(m
.m_tty
) - 1] = 0;
646 if (nwin
->args
!= nwin_undef
.args
)
647 for (av
= nwin
->args
; *av
&& n
< MAXARGS
- 1; ++av
, ++n
)
649 len
= strlen(*av
) + 1;
650 if (p
+ len
>= m
.m
.create
.line
+ sizeof(m
.m
.create
.line
) - 1)
655 if (nwin
->aka
!= nwin_undef
.aka
&& p
+ strlen(nwin
->aka
) + 1 < m
.m
.create
.line
+ sizeof(m
.m
.create
.line
))
656 strcpy(p
, nwin
->aka
);
659 m
.m
.create
.nargs
= n
;
660 m
.m
.create
.aflag
= nwin
->aflag
;
661 m
.m
.create
.flowflag
= nwin
->flowflag
;
662 m
.m
.create
.lflag
= nwin
->lflag
;
663 m
.m
.create
.hheight
= nwin
->histheight
;
664 if (getcwd(m
.m
.create
.dir
, sizeof(m
.m
.create
.dir
)) == 0)
666 Msg(errno
, "getcwd");
669 if (nwin
->term
!= nwin_undef
.term
)
670 strncpy(m
.m
.create
.screenterm
, nwin
->term
, 19);
671 m
.m
.create
.screenterm
[19] = '\0';
672 m
.protocol_revision
= MSG_REVISION
;
673 debug1("SendCreateMsg writing '%s'\n", m
.m
.create
.line
);
674 if (write(s
, (char *) &m
, sizeof m
) != sizeof m
)
680 SendErrorMsg(tty
, buf
)
686 strncpy(m
.m
.message
, buf
, sizeof(m
.m
.message
) - 1);
687 m
.m
.message
[sizeof(m
.m
.message
) - 1] = 0;
688 s
= MakeClientSocket(0);
692 strncpy(m
.m_tty
, tty
, sizeof(m
.m_tty
) - 1);
693 m
.m_tty
[sizeof(m
.m_tty
) - 1] = 0;
694 m
.protocol_revision
= MSG_REVISION
;
695 debug1("SendErrorMsg(): writing to '%s'\n", SockPath
);
696 (void) write(s
, (char *) &m
, sizeof m
);
705 struct NewWindow nwin
;
708 register char **pp
= args
, *p
= mp
->m
.create
.line
;
711 n
= mp
->m
.create
.nargs
;
714 /* ugly hack alert... should be done by the frontend! */
721 if (IsNumColon(p
, 10, buf
, sizeof(buf
)))
726 if (num
< 0 || num
> MAXWIN
- 1)
743 nwin
.aflag
= mp
->m
.create
.aflag
;
744 nwin
.flowflag
= mp
->m
.create
.flowflag
;
745 if (*mp
->m
.create
.dir
)
746 nwin
.dir
= mp
->m
.create
.dir
;
747 nwin
.lflag
= mp
->m
.create
.lflag
;
748 nwin
.histheight
= mp
->m
.create
.hheight
;
749 if (*mp
->m
.create
.screenterm
)
750 nwin
.term
= mp
->m
.create
.screenterm
;
758 debug1("Checking pid %d\n", pid
);
761 if (eff_uid
== real_uid
)
763 if (UserContext() > 0)
764 UserReturn(kill(pid
, 0));
770 * From: "F. K. Bruner" <napalm@ugcs.caltech.edu>
771 * From: "Dan Egnor" <egnor@oracorp.com> Tue Aug 10 06:56:45 1993
772 * The problem is that under HPUX (and possibly other systems too) there are
773 * two equivalent device files for each pty/tty device:
774 * /dev/ttyxx == /dev/pty/ttyxx
775 * /dev/ptyxx == /dev/ptym/ptyxx
776 * I didn't look into the exact specifics, but I've run across this problem
777 * before: Even if you open /dev/ttyxx as fds 0 1 & 2 for a process, if that
778 * process calls the system to determine its tty, it'll get /dev/pty/ttyxx.
780 * Earlier versions seemed to work -- wonder what they did.
786 if (strlen(s1
) > 5) s1
+= strlen(s1
) - 5;
787 if (strlen(s2
) > 5) s2
+= strlen(s2
) - 5;
788 return strcmp(s1
, s2
);
790 # define TTYCMP(a, b) ttycmp(a, b)
792 # define TTYCMP(a, b) strcmp(a, b)
796 CreateTempDisplay(m
, recvfd
, wi
)
806 struct display
*olddisplays
= displays
;
812 pid
= m
->m
.attach
.apid
;
813 user
= m
->m
.attach
.auser
;
820 # endif /* POW_DETACH */
821 pid
= m
->m
.detach
.dpid
;
822 user
= m
->m
.detach
.duser
;
832 Msg(0, "Attach attempt with bad pid(%d)!", pid
);
840 myttyname
= ttyname(i
);
841 if (myttyname
== 0 || strcmp(myttyname
, m
->m_tty
))
843 Msg(errno
, "Attach: passed fd does not match tty: %s - %s!", m
->m_tty
, myttyname
? myttyname
: "NULL");
849 else if ((i
= secopen(m
->m_tty
, O_RDWR
| O_NONBLOCK
, 0)) < 0)
851 Msg(errno
, "Attach: Could not open %s!", m
->m_tty
);
860 #if defined(ultrix) || defined(pyr) || defined(NeXT)
861 brktty(i
); /* for some strange reason this must be done */
868 write(i
, "Attaching from inside of screen?\n", 33);
871 Msg(0, "Attach msg ignored: coming from inside.");
876 if (strcmp(user
, LoginName
))
877 if (*FindUserPtr(user
) == 0)
879 write(i
, "Access to session denied.\n", 26);
882 Msg(0, "Attach: access denied for user %s.", user
);
887 debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", pid
, m
->m_tty
);
891 write(i
, "Screen session in use.\n", 23);
899 /* create new display */
901 if (MakeDisplay(user
, m
->m_tty
, attach
? m
->m
.attach
.envterm
: "", i
, pid
, &Mode
) == 0)
903 write(i
, "Could not make display.\n", 24);
905 Msg(0, "Attach: could not make display for user %s", user
);
913 D_encoding
= m
->m
.attach
.encoding
== 1 ? UTF8
: m
->m
.attach
.encoding
? m
->m
.attach
.encoding
- 1 : 0;
915 D_encoding
= m
->m
.attach
.encoding
? m
->m
.attach
.encoding
- 1 : 0;
917 if (D_encoding
< 0 || !EncodingName(D_encoding
))
922 if (iflag
&& olddisplays
)
925 #if defined(TERMIO) || defined(POSIX)
926 olddisplays
->d_NewMode
.tio
.c_cc
[VINTR
] = VDISABLE
;
927 olddisplays
->d_NewMode
.tio
.c_lflag
&= ~ISIG
;
928 #else /* TERMIO || POSIX */
929 olddisplays
->d_NewMode
.m_tchars
.t_intrc
= -1;
930 #endif /* TERMIO || POSIX */
931 SetTTY(olddisplays
->d_userfd
, &olddisplays
->d_NewMode
);
933 SetMode(&D_OldMode
, &D_NewMode
, D_flow
, iflag
);
934 SetTTY(D_userfd
, &D_NewMode
);
935 if (fcntl(D_userfd
, F_SETFL
, FNBLOCK
))
936 Msg(errno
, "Warning: NBLOCK fcntl failed");
946 int ns
= ServerSocket
;
949 struct acluser
*user
;
952 debug("Ha, there was someone knocking on my fifo??\n");
953 if (fcntl(ServerSocket
, F_SETFL
, 0) == -1)
954 Panic(errno
, "BLOCK fcntl");
958 struct sockaddr_un a
;
964 debug("Ha, there was someone knocking on my socket??\n");
965 if ((ns
= accept(ns
, (struct sockaddr
*) &a
, (void *)&len
)) < 0)
967 Msg(errno
, "accept");
973 bzero(&msg
, sizeof(msg
));
978 msg
.msg_controllen
= sizeof(control
);
979 msg
.msg_control
= &control
;
982 len
= recvmsg(ns
, &msg
, 0);
983 if (len
< 0 && errno
== EINTR
)
991 if (msg
.msg_controllen
)
993 struct cmsghdr
*cmsg
;
994 for (cmsg
= CMSG_FIRSTHDR(&msg
); cmsg
; cmsg
= CMSG_NXTHDR(&msg
, cmsg
))
998 if (cmsg
->cmsg_level
!= SOL_SOCKET
|| cmsg
->cmsg_type
!= SCM_RIGHTS
)
1000 cp
= (char *)CMSG_DATA(cmsg
);
1001 cl
= cmsg
->cmsg_len
;
1002 while(cl
>= CMSG_LEN(sizeof(int)))
1005 bcopy(cp
, &passedfd
, sizeof(int));
1006 if (recvfd
>= 0 && passedfd
!= recvfd
)
1009 cl
-= CMSG_LEN(sizeof(int));
1022 len
= read(ns
, p
, left
);
1023 if (len
< 0 && errno
== EINTR
)
1032 # ifndef BROKEN_PIPE
1033 /* Reopen pipe to prevent EOFs at the select() call */
1034 close(ServerSocket
);
1035 if ((ServerSocket
= secopen(SockPath
, O_RDONLY
| O_NONBLOCK
, 0)) < 0)
1036 Panic(errno
, "reopen fifo %s", SockPath
);
1038 serv_read
.fd
= ServerSocket
;
1054 if (left
!= sizeof(m
))
1055 Msg(0, "Message %d of %d bytes too small", left
, (int)sizeof(m
));
1057 debug("No data on socket.\n");
1060 if (m
.protocol_revision
!= MSG_REVISION
)
1064 Msg(0, "Invalid message (magic 0x%08x).", m
.protocol_revision
);
1068 debug2("*** RecMsg: type %d tty %s\n", m
.type
, m
.m_tty
);
1069 if (m
.type
!= MSG_ATTACH
&& recvfd
!= -1)
1075 for (display
= displays
; display
; display
= display
->d_next
)
1076 if (TTYCMP(D_usertty
, m
.m_tty
) == 0)
1078 debug2("display: %s display %sfound\n", m
.m_tty
, display
? "" : "not ");
1082 for (wi
= windows
; wi
; wi
= wi
->w_next
)
1083 if (!TTYCMP(m
.m_tty
, wi
->w_tty
))
1085 /* XXX: hmmm, rework this? */
1086 display
= wi
->w_layer
.l_cvlist
? wi
->w_layer
.l_cvlist
->c_display
: 0;
1087 debug2("but window %s %sfound.\n", m
.m_tty
, display
? "" :
1093 /* Remove the status to prevent garbage on the screen */
1094 if (display
&& D_status
)
1097 if (display
&& !D_tcinited
&& m
.type
!= MSG_HANGUP
)
1101 return; /* ignore messages for bad displays */
1108 CheckScreenSize(1); /* Change fore */
1112 * the window that issued the create message need not be an active
1113 * window. Then we create the window without having a display.
1114 * Resulting in another inactive window.
1119 if (display
&& D_userpid
!= 0 && kill(D_userpid
, 0) == 0)
1120 break; /* Intruder Alert */
1121 debug2("RecMsg: apid=%d,was %d\n", m
.m
.attach
.apid
, display
? D_userpid
: 0);
1125 if (CreateTempDisplay(&m
, recvfd
, wi
))
1128 if (D_user
->u_password
&& *D_user
->u_password
)
1135 Msg(0, "%s", m
.m
.message
);
1138 if (!wi
) /* ignore hangups from inside */
1141 #ifdef REMOTE_DETACH
1144 case MSG_POW_DETACH
:
1145 # endif /* POW_DETACH */
1147 user
= *FindUserPtr(m
.m
.detach
.duser
);
1148 if (user
&& user
->u_password
&& *user
->u_password
)
1150 if (CreateTempDisplay(&m
, recvfd
, 0))
1155 #endif /* PASSWORD */
1163 Msg(0, "Invalid message (type %d).", m
.type
);
1167 #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
1170 * sequent_ptx socket emulation must have mode 000 on the socket!
1173 sconnect(s
, sapp
, len
)
1175 struct sockaddr
*sapp
;
1177 register struct sockaddr_un
*sap
;
1181 sap
= (struct sockaddr_un
*)sapp
;
1182 if (stat(sap
->sun_path
, &st
))
1184 chmod(sap
->sun_path
, 0);
1185 x
= connect(s
, (struct sockaddr
*) sap
, len
);
1186 chmod(sap
->sun_path
, st
.st_mode
);
1193 * Set the mode bits of the socket to the current status
1198 int r
, euid
= geteuid();
1199 if (euid
!= real_uid
)
1201 if (UserContext() <= 0)
1202 return UserStatus();
1204 r
= chmod(SockPath
, SOCKMODE
);
1206 * Sockets usually reside in the /tmp/ area, where sysadmin scripts
1207 * may be happy to remove old files. We manually prevent the socket
1208 * from becoming old. (chmod does not touch mtime).
1210 (void)utimes(SockPath
, NULL
);
1212 if (euid
!= real_uid
)
1218 * Try to recreate the socket/pipe
1223 close(ServerSocket
);
1224 if ((int)geteuid() != real_uid
)
1226 if (UserContext() > 0)
1227 UserReturn(unlink(SockPath
));
1231 (void) unlink(SockPath
);
1233 if ((ServerSocket
= MakeServerSocket()) < 0)
1236 serv_read
.fd
= ServerSocket
;
1254 #ifdef REMOTE_DETACH
1255 if (m
->m
.attach
.detachfirst
== MSG_DETACH
1257 || m
->m
.attach
.detachfirst
== MSG_POW_DETACH
1263 #if defined(pyr) || defined(xelos) || defined(sequent)
1265 * Kludge for systems with braindamaged termcap routines,
1266 * which evaluate $TERMCAP, regardless weather it describes
1267 * the correct terminal type or not.
1269 debug("unsetenv(TERMCAP) in case of a different terminal");
1270 unsetenv("TERMCAP");
1274 * We reboot our Terminal Emulator. Forget all we knew about
1275 * the old terminal, reread the termcap entries in .screenrc
1276 * (and nothing more from .screenrc is read. Mainly because
1277 * I did not check, weather a full reinit is safe. jw)
1278 * and /etc/screenrc, and initialise anew.
1284 extra_incap
= extra_outcap
= 0;
1285 debug2("Message says size (%dx%d)\n", m
->m
.attach
.columns
, m
->m
.attach
.lines
);
1287 # ifdef ALLOW_SYSSCREENRC
1288 if ((p
= getenv("SYSSCREENRC")))
1292 StartRc(ETCSCREENRC
, 1);
1294 StartRc(RcFileName
, 1);
1295 if (InitTermcap(m
->m
.attach
.columns
, m
->m
.attach
.lines
))
1301 MakeDefaultCanvas();
1302 InitTerm(m
->m
.attach
.adaptflag
); /* write init string on fd */
1303 if (displays
->d_next
== 0)
1305 signal(SIGHUP
, SigHup
);
1306 if (m
->m
.attach
.esc
!= -1 && m
->m
.attach
.meta_esc
!= -1)
1308 D_user
->u_Esc
= m
->m
.attach
.esc
;
1309 D_user
->u_MetaEsc
= m
->m
.attach
.meta_esc
;
1314 * we set the Utmp slots again, if we were detached normally
1315 * and if we were detached by ^Z.
1316 * don't log zomies back in!
1319 if (displays
->d_next
== 0)
1320 for (wi
= windows
; wi
; wi
= wi
->w_next
)
1321 if (wi
->w_ptyfd
>= 0 && wi
->w_slot
!= (slot_t
) -1)
1328 struct layout
*lay
= layout_attach
;
1329 if (lay
== &layout_last_marker
)
1333 LoadLayout(lay
, &D_canvas
);
1334 SetCanvasWindow(D_forecv
, 0);
1338 * there may be a window that we remember from last detach:
1340 debug1("D_user->u_detachwin = %d\n", D_user
->u_detachwin
);
1341 if (D_user
->u_detachwin
>= 0)
1342 fore
= wtab
[D_user
->u_detachwin
];
1346 /* Wayne wants us to restore the other window too. */
1347 if (D_user
->u_detachotherwin
>= 0)
1348 D_other
= wtab
[D_user
->u_detachotherwin
];
1351 if (*m
->m
.attach
.preselect
)
1353 if (!strcmp(m
->m
.attach
.preselect
, "="))
1355 else if (!strcmp(m
->m
.attach
.preselect
, "-"))
1360 else if (!strcmp(m
->m
.attach
.preselect
, "+"))
1362 struct action newscreen
;
1364 newscreen
.nr
= RC_SCREEN
;
1365 newscreen
.args
= &na
;
1366 DoAction(&newscreen
, -1);
1369 fore
= FindNiceWindow(fore
, m
->m
.attach
.preselect
);
1372 fore
= FindNiceWindow(fore
, 0);
1374 SetForeWindow(fore
);
1375 else if (!noshowwin
)
1378 if (!AclCheckPermCmd(D_user
, ACL_EXEC
, &comms
[RC_WINDOWLIST
]))
1381 flayer
= D_forecv
->c_layer
;
1382 display_wlist(1, WLIST_NUM
, (struct win
*)0);
1388 if (!D_fore
&& !noshowwin
)
1390 if (displays
->d_next
== 0 && console_window
)
1392 if (TtyGrabConsole(console_window
->w_ptyfd
, 1, "reattach") == 0)
1393 Msg(0, "console %s is on window %d", HostName
, console_window
->w_number
);
1395 debug("activated...\n");
1397 # if defined(DEBUG) && defined(SIG_NODEBUG)
1401 debug1("Attacher %d must not debug, as we have debug off.\n", pid
);
1402 kill(pid
, SIG_NODEBUG
);
1404 # endif /* SIG_NODEBUG */
1411 struct display
*next
, **d
, *det
;
1414 if (m
->type
== MSG_ATTACH
)
1417 pid
= m
->m
.detach
.dpid
;
1419 /* Remove the temporary display prompting for the password from the list */
1420 for (d
= &displays
; (det
= *d
); d
= &det
->d_next
)
1422 if (det
->d_userpid
== pid
)
1431 for (display
= displays
; display
; display
= next
)
1433 next
= display
->d_next
;
1435 if (m
->type
== MSG_POW_DETACH
)
1436 Detach(D_REMOTE_POWER
);
1438 # endif /* POW_DETACH */
1439 if (m
->type
== MSG_DETACH
)
1441 else if (m
->type
== MSG_ATTACH
)
1444 if (m
->m
.attach
.detachfirst
== MSG_POW_DETACH
)
1445 Detach(D_REMOTE_POWER
);
1448 if (m
->m
.attach
.detachfirst
== MSG_DETACH
)
1452 display
= displays
= det
;
1453 if (m
->type
!= MSG_ATTACH
)
1462 static void PasswordProcessInput
__P((char *, int));
1474 struct pwdata
*pwdata
;
1476 pwdata
= (struct pwdata
*)malloc(sizeof(struct pwdata
));
1481 D_processinputdata
= (char *)pwdata
;
1482 D_processinput
= PasswordProcessInput
;
1483 AddStr("Screen password: ");
1487 PasswordProcessInput(ibuf
, ilen
)
1491 struct pwdata
*pwdata
;
1494 int pid
= D_userpid
;
1496 pwdata
= (struct pwdata
*)D_processinputdata
;
1500 c
= *(unsigned char *)ibuf
++;
1501 if (c
== '\r' || c
== '\n')
1503 up
= D_user
->u_password
;
1505 if (strncmp(crypt(pwdata
->buf
, up
), up
, strlen(up
)))
1507 /* uh oh, user failed */
1508 bzero(pwdata
->buf
, sizeof(pwdata
->buf
));
1509 AddStr("\r\nPassword incorrect.\r\n");
1510 D_processinputdata
= 0; /* otherwise freed by FreeDis */
1512 Msg(0, "Illegal reattach attempt from terminal %s.", pwdata
->m
.m_tty
);
1517 /* great, pw matched, all is fine */
1518 bzero(pwdata
->buf
, sizeof(pwdata
->buf
));
1520 D_processinputdata
= 0;
1521 D_processinput
= ProcessInput
;
1522 #ifdef REMOTE_DETACH
1523 if (pwdata
->m
.type
== MSG_DETACH
1525 || pwdata
->m
.type
== MSG_POW_DETACH
1528 FinishDetach(&pwdata
->m
);
1531 FinishAttach(&pwdata
->m
);
1542 if (c
== '\b' || c
== 0177)
1553 if (l
< (int)sizeof(pwdata
->buf
) - 1)
1554 pwdata
->buf
[l
++] = c
;
1564 char *args
[MAXARGS
];
1566 char fullcmd
[MAXSTR
];
1569 register char *p
= mp
->m
.command
.cmd
;
1570 struct acluser
*user
;
1572 extern struct acluser
*EffectiveAclUser
; /* acls.c */
1574 extern struct acluser
*users
; /* acls.c */
1577 n
= mp
->m
.command
.nargs
;
1578 if (n
> MAXARGS
- 1)
1580 for (fc
= fullcmd
; n
> 0; n
--)
1582 int len
= strlen(p
);
1583 strncpy(fc
, p
, fullcmd
+ sizeof(fullcmd
) - fc
- 1);
1590 if (Parse(fullcmd
, fc
- fullcmd
, args
, argl
) <= 0)
1593 user
= *FindUserPtr(mp
->m
.attach
.auser
);
1596 Msg(0, "Unknown user %s tried to send a command!", mp
->m
.attach
.auser
);
1603 if (user
->u_password
&& *user
->u_password
)
1605 Msg(0, "User %s has a password, cannot use -X option.", mp
->m
.attach
.auser
);
1610 for (display
= displays
; display
; display
= display
->d_next
)
1613 for (fore
= windows
; fore
; fore
= fore
->w_next
)
1614 if (!TTYCMP(mp
->m_tty
, fore
->w_tty
))
1617 display
= fore
->w_layer
.l_cvlist
? fore
->w_layer
.l_cvlist
->c_display
: 0;
1621 display
= displays
; /* sigh */
1622 if (*mp
->m
.command
.preselect
)
1625 if (strcmp(mp
->m
.command
.preselect
, "-"))
1626 i
= WindowByNoN(mp
->m
.command
.preselect
);
1627 fore
= i
>= 0 ? wtab
[i
] : 0;
1631 if (display
&& D_user
== user
)
1632 fore
= Layer2Window(display
->d_forecv
->c_layer
);
1635 fore
= user
->u_detachwin
>= 0 ? wtab
[user
->u_detachwin
] : 0;
1636 fore
= FindNiceWindow(fore
, 0);
1640 fore
= windows
; /* sigh */
1642 EffectiveAclUser
= user
;
1646 char *oldrcname
= rc_name
;
1648 debug3("Running command on display %x window %x (%d)\n", display
, fore
, fore
? fore
->w_number
: -1);
1649 flayer
= fore
? &fore
->w_layer
: 0;
1650 if (fore
&& fore
->w_savelayer
&& (fore
->w_blocked
|| fore
->w_savelayer
->l_cvlist
== 0))
1651 flayer
= fore
->w_savelayer
;
1652 DoCommand(args
, argl
);
1653 rc_name
= oldrcname
;
1656 EffectiveAclUser
= 0;
1663 SendAttachMsg(s
, m
, fd
)
1671 char buf
[CMSG_SPACE(sizeof(int))];
1672 struct cmsghdr
*cmsg
;
1674 iov
.iov_base
= (char *)m
;
1675 iov
.iov_len
= sizeof(*m
);
1676 bzero(&msg
, sizeof(msg
));
1678 msg
.msg_namelen
= 0;
1681 msg
.msg_control
= buf
;
1682 msg
.msg_controllen
= sizeof(buf
);
1683 cmsg
= CMSG_FIRSTHDR(&msg
);
1684 cmsg
->cmsg_level
= SOL_SOCKET
;
1685 cmsg
->cmsg_type
= SCM_RIGHTS
;
1686 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
1687 bcopy(&fd
, CMSG_DATA(cmsg
), sizeof(int));
1688 msg
.msg_controllen
= cmsg
->cmsg_len
;
1691 r
= sendmsg(s
, &msg
, 0);
1692 if (r
== -1 && errno
== EINTR
)