2562 lines
56 KiB
C
2562 lines
56 KiB
C
/*
|
||
|
||
Copyright 1993, 1994, 1998 The Open Group
|
||
|
||
Permission to use, copy, modify, distribute, and sell this software and its
|
||
documentation for any purpose is hereby granted without fee, provided that
|
||
the above copyright notice appear in all copies and that both that
|
||
copyright notice and this permission notice appear in supporting
|
||
documentation.
|
||
|
||
The above copyright notice and this permission notice shall be included
|
||
in all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
Except as contained in this notice, the name of The Open Group shall
|
||
not be used in advertising or otherwise to promote the sale, use or
|
||
other dealings in this Software without prior written authorization
|
||
from The Open Group.
|
||
|
||
* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
|
||
*
|
||
* All Rights Reserved
|
||
*
|
||
* Permission to use, copy, modify, and distribute this software and its
|
||
* documentation for any purpose and without fee is hereby granted, provided
|
||
* that the above copyright notice appear in all copies and that both that
|
||
* copyright notice and this permission notice appear in supporting
|
||
* documentation, and that the name NCR not be used in advertising
|
||
* or publicity pertaining to distribution of the software without specific,
|
||
* written prior permission. NCR makes no representations about the
|
||
* suitability of this software for any purpose. It is provided "as is"
|
||
* without express or implied warranty.
|
||
*
|
||
* NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
||
* NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
*/
|
||
|
||
/*
|
||
*
|
||
* The connection code/ideas in lib/X and server/os for SVR4/Intel
|
||
* environments was contributed by the following companies/groups:
|
||
*
|
||
* MetroLink Inc
|
||
* NCR
|
||
* Pittsburgh Powercomputing Corporation (PPc)/Quarterdeck Office Systems
|
||
* SGCS
|
||
* Unix System Laboratories (USL) / Novell
|
||
* XFree86
|
||
*
|
||
* The goal is to have common connection code among all SVR4/Intel vendors.
|
||
*
|
||
* ALL THE ABOVE COMPANIES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
|
||
* IN NO EVENT SHALL THESE COMPANIES * BE LIABLE FOR ANY SPECIAL, INDIRECT
|
||
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
|
||
* OR PERFORMANCE OF THIS SOFTWARE.
|
||
*/
|
||
|
||
#include <errno.h>
|
||
#include <ctype.h>
|
||
#include <sys/signal.h>
|
||
#include <sys/ioctl.h>
|
||
#include <sys/stat.h>
|
||
#if defined(SVR4) || defined(__SVR4)
|
||
#include <sys/filio.h>
|
||
#endif
|
||
#ifdef sun
|
||
# include <stropts.h>
|
||
#else
|
||
# include <sys/stropts.h>
|
||
#endif
|
||
#include <sys/wait.h>
|
||
#include <sys/types.h>
|
||
|
||
/*
|
||
* The local transports should be treated the same as a UNIX domain socket
|
||
* wrt authentication, etc. Because of this, we will use struct sockaddr_un
|
||
* for the address format. This will simplify the code in other places like
|
||
* The X Server.
|
||
*/
|
||
|
||
#include <sys/socket.h>
|
||
#ifndef X_NO_SYS_UN
|
||
#include <sys/un.h>
|
||
#endif
|
||
|
||
|
||
/* Types of local connections supported:
|
||
* - PTS
|
||
* - named pipes
|
||
* - ISC
|
||
* - SCO
|
||
*/
|
||
#if !defined(sun)
|
||
# define LOCAL_TRANS_PTS
|
||
#endif
|
||
#if defined(SVR4) || defined(__SVR4)
|
||
# define LOCAL_TRANS_NAMED
|
||
#endif
|
||
#if defined(__SCO__) || defined(__UNIXWARE__)
|
||
# define LOCAL_TRANS_SCO
|
||
#endif
|
||
|
||
static int TRANS(LocalClose)(XtransConnInfo ciptr);
|
||
|
||
/*
|
||
* These functions actually implement the local connection mechanisms.
|
||
*/
|
||
|
||
/* Type Not Supported */
|
||
|
||
static int
|
||
TRANS(OpenFail)(XtransConnInfo ciptr, char *port)
|
||
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
#ifdef TRANS_REOPEN
|
||
|
||
static int
|
||
TRANS(ReopenFail)(XtransConnInfo ciptr, int fd, char *port)
|
||
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
#endif /* TRANS_REOPEN */
|
||
|
||
|
||
|
||
static int
|
||
TRANS(FillAddrInfo)(XtransConnInfo ciptr, char *sun_path, char *peer_sun_path)
|
||
|
||
{
|
||
struct sockaddr_un *sunaddr;
|
||
struct sockaddr_un *p_sunaddr;
|
||
|
||
ciptr->family = AF_UNIX;
|
||
ciptr->addrlen = sizeof (struct sockaddr_un);
|
||
|
||
if ((sunaddr = (struct sockaddr_un *) xalloc (ciptr->addrlen)) == NULL)
|
||
{
|
||
PRMSG(1,"FillAddrInfo: failed to allocate memory for addr\n", 0, 0, 0);
|
||
return 0;
|
||
}
|
||
|
||
sunaddr->sun_family = AF_UNIX;
|
||
|
||
if (strlen(sun_path) > sizeof(sunaddr->sun_path) - 1) {
|
||
PRMSG(1, "FillAddrInfo: path too long\n", 0, 0, 0);
|
||
return 0;
|
||
}
|
||
strcpy (sunaddr->sun_path, sun_path);
|
||
#if defined(BSD44SOCKETS)
|
||
sunaddr->sun_len = strlen (sunaddr->sun_path);
|
||
#endif
|
||
|
||
ciptr->addr = (char *) sunaddr;
|
||
|
||
ciptr->peeraddrlen = sizeof (struct sockaddr_un);
|
||
|
||
if ((p_sunaddr = (struct sockaddr_un *) xalloc (
|
||
ciptr->peeraddrlen)) == NULL)
|
||
{
|
||
PRMSG(1,
|
||
"FillAddrInfo: failed to allocate memory for peer addr\n",
|
||
0,0,0);
|
||
xfree ((char *) sunaddr);
|
||
ciptr->addr = NULL;
|
||
|
||
return 0;
|
||
}
|
||
|
||
p_sunaddr->sun_family = AF_UNIX;
|
||
|
||
if (strlen(peer_sun_path) > sizeof(p_sunaddr->sun_path) - 1) {
|
||
PRMSG(1, "FillAddrInfo: peer path too long\n", 0, 0, 0);
|
||
return 0;
|
||
}
|
||
strcpy (p_sunaddr->sun_path, peer_sun_path);
|
||
#if defined(BSD44SOCKETS)
|
||
p_sunaddr->sun_len = strlen (p_sunaddr->sun_path);
|
||
#endif
|
||
|
||
ciptr->peeraddr = (char *) p_sunaddr;
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
|
||
#ifdef LOCAL_TRANS_PTS
|
||
/* PTS */
|
||
|
||
#if defined(SYSV) && !defined(__SCO__)
|
||
#define SIGNAL_T int
|
||
#else
|
||
#define SIGNAL_T void
|
||
#endif /* SYSV */
|
||
|
||
typedef SIGNAL_T (*PFV)();
|
||
|
||
extern PFV signal();
|
||
|
||
extern char *ptsname(
|
||
int
|
||
);
|
||
|
||
static void _dummy(int sig)
|
||
|
||
{
|
||
}
|
||
#endif /* LOCAL_TRANS_PTS */
|
||
|
||
#ifndef sun
|
||
#define X_STREAMS_DIR "/dev/X"
|
||
#define DEV_SPX "/dev/spx"
|
||
#else
|
||
#ifndef X11_t
|
||
#define X_STREAMS_DIR "/dev/X"
|
||
#else
|
||
#define X_STREAMS_DIR "/tmp/.X11-pipe"
|
||
#endif
|
||
#endif
|
||
|
||
#define DEV_PTMX "/dev/ptmx"
|
||
|
||
#if defined(X11_t)
|
||
|
||
#define PTSNODENAME "/dev/X/server."
|
||
#ifdef sun
|
||
#define NAMEDNODENAME "/tmp/.X11-pipe/X"
|
||
#else
|
||
#define NAMEDNODENAME "/dev/X/Nserver."
|
||
|
||
/*
|
||
* ISC is only defined for X11 since they are there for
|
||
* backwards binary compatability only.
|
||
*/
|
||
|
||
#define SCORNODENAME "/dev/X%1sR"
|
||
#define SCOSNODENAME "/dev/X%1sS"
|
||
#endif /* !sun */
|
||
#endif
|
||
#if defined(XIM_t)
|
||
#ifdef sun
|
||
#define NAMEDNODENAME "/tmp/.XIM-pipe/XIM"
|
||
#else
|
||
#define PTSNODENAME "/dev/X/XIM."
|
||
#define NAMEDNODENAME "/dev/X/NXIM."
|
||
#define SCORNODENAME "/dev/XIM.%sR"
|
||
#define SCOSNODENAME "/dev/XIM.%sS"
|
||
#endif
|
||
#endif
|
||
#if defined(FS_t) || defined (FONT_t)
|
||
#ifdef sun
|
||
#define NAMEDNODENAME "/tmp/.font-pipe/fs"
|
||
#else
|
||
/*
|
||
* USL has already defined something here. We need to check with them
|
||
* and see if their choice is usable here.
|
||
*/
|
||
#define PTSNODENAME "/dev/X/fontserver."
|
||
#define NAMEDNODENAME "/dev/X/Nfontserver."
|
||
#define SCORNODENAME "/dev/fontserver.%sR"
|
||
#define SCOSNODENAME "/dev/fontserver.%sS"
|
||
#endif
|
||
#endif
|
||
#if defined(ICE_t)
|
||
#ifdef sun
|
||
#define NAMEDNODENAME "/tmp/.ICE-pipe/"
|
||
#else
|
||
#define PTSNODENAME "/dev/X/ICE."
|
||
#define NAMEDNODENAME "/dev/X/NICE."
|
||
#define SCORNODENAME "/dev/ICE.%sR"
|
||
#define SCOSNODENAME "/dev/ICE.%sS"
|
||
#endif
|
||
#endif
|
||
#if defined(TEST_t)
|
||
#ifdef sun
|
||
#define NAMEDNODENAME "/tmp/.Test-unix/test"
|
||
#endif
|
||
#define PTSNODENAME "/dev/X/transtest."
|
||
#define NAMEDNODENAME "/dev/X/Ntranstest."
|
||
#define SCORNODENAME "/dev/transtest.%sR"
|
||
#define SCOSNODENAME "/dev/transtest.%sS"
|
||
#endif
|
||
|
||
|
||
|
||
#ifdef LOCAL_TRANS_PTS
|
||
#ifdef TRANS_CLIENT
|
||
|
||
static int
|
||
TRANS(PTSOpenClient)(XtransConnInfo ciptr, char *port)
|
||
|
||
{
|
||
#ifdef PTSNODENAME
|
||
int fd,server,exitval,alarm_time,ret;
|
||
char server_path[64];
|
||
char *slave, namelen;
|
||
char buf[20]; /* MAX_PATH_LEN?? */
|
||
PFV savef;
|
||
pid_t saved_pid;
|
||
#endif
|
||
|
||
PRMSG(2,"PTSOpenClient(%s)\n", port, 0,0 );
|
||
|
||
#if !defined(PTSNODENAME)
|
||
PRMSG(1,"PTSOpenClient: Protocol is not supported by a pts connection\n", 0,0,0);
|
||
return -1;
|
||
#else
|
||
if (port && *port ) {
|
||
if( *port == '/' ) { /* A full pathname */
|
||
(void) sprintf(server_path, "%s", port);
|
||
} else {
|
||
(void) sprintf(server_path, "%s%s", PTSNODENAME, port);
|
||
}
|
||
} else {
|
||
(void) sprintf(server_path, "%s%d", PTSNODENAME, getpid());
|
||
}
|
||
|
||
|
||
/*
|
||
* Open the node the on which the server is listening.
|
||
*/
|
||
|
||
if ((server = open (server_path, O_RDWR)) < 0) {
|
||
PRMSG(1,"PTSOpenClient: failed to open %s\n", server_path, 0,0);
|
||
return -1;
|
||
}
|
||
|
||
|
||
/*
|
||
* Open the streams based pipe that will be this connection.
|
||
*/
|
||
|
||
if ((fd = open(DEV_PTMX, O_RDWR)) < 0) {
|
||
PRMSG(1,"PTSOpenClient: failed to open %s\n", DEV_PTMX, 0,0);
|
||
return(-1);
|
||
}
|
||
|
||
(void) grantpt(fd);
|
||
(void) unlockpt(fd);
|
||
|
||
slave = ptsname(fd); /* get name */
|
||
|
||
if( slave == NULL ) {
|
||
PRMSG(1,"PTSOpenClient: failed to get ptsname()\n", 0,0,0);
|
||
close(fd);
|
||
close(server);
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* This is neccesary for the case where a program is setuid to non-root.
|
||
* grantpt() calls /usr/lib/pt_chmod which is set-uid root. This program will
|
||
* set the owner of the pt device incorrectly if the uid is not restored
|
||
* before it is called. The problem is that once it gets restored, it
|
||
* cannot be changed back to its original condition, hence the fork().
|
||
*/
|
||
|
||
if(!(saved_pid=fork())) {
|
||
uid_t saved_euid;
|
||
|
||
saved_euid = geteuid();
|
||
/** sets the euid to the actual/real uid **/
|
||
if (setuid( getuid() ) == -1) {
|
||
exit(1);
|
||
}
|
||
if( chown( slave, saved_euid, -1 ) < 0 ) {
|
||
exit( 1 );
|
||
}
|
||
|
||
exit( 0 );
|
||
}
|
||
|
||
waitpid(saved_pid, &exitval, 0);
|
||
if (WIFEXITED(exitval) && WEXITSTATUS(exitval) != 0) {
|
||
close(fd);
|
||
close(server);
|
||
PRMSG(1, "PTSOpenClient: cannot set the owner of %s\n",
|
||
slave, 0, 0);
|
||
return(-1);
|
||
}
|
||
if (chmod(slave, 0666) < 0) {
|
||
close(fd);
|
||
close(server);
|
||
PRMSG(1,"PTSOpenClient: Cannot chmod %s\n", slave, 0,0);
|
||
return(-1);
|
||
}
|
||
|
||
/*
|
||
* write slave name to server
|
||
*/
|
||
|
||
namelen = strlen(slave);
|
||
buf[0] = namelen;
|
||
(void) sprintf(&buf[1], slave);
|
||
(void) write(server, buf, namelen+1);
|
||
(void) close(server);
|
||
|
||
/*
|
||
* wait for server to respond
|
||
*/
|
||
|
||
savef = signal(SIGALRM, _dummy);
|
||
alarm_time = alarm (30); /* CONNECT_TIMEOUT */
|
||
|
||
ret = read(fd, buf, 1);
|
||
|
||
(void) alarm(alarm_time);
|
||
(void) signal(SIGALRM, savef);
|
||
|
||
if (ret != 1) {
|
||
PRMSG(1,
|
||
"PTSOpenClient: failed to get acknoledgement from server\n", 0, 0, 0);
|
||
(void) close(fd);
|
||
fd = -1;
|
||
}
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
if (TRANS(FillAddrInfo) (ciptr, slave, server_path) == 0)
|
||
{
|
||
PRMSG(1,"PTSOpenClient: failed to fill in addr info\n", 0, 0, 0);
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
return(fd);
|
||
|
||
#endif /* !PTSNODENAME */
|
||
}
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
static int
|
||
TRANS(PTSOpenServer)(XtransConnInfo ciptr, char *port)
|
||
|
||
{
|
||
#ifdef PTSNODENAME
|
||
int fd, server;
|
||
char server_path[64], *slave;
|
||
int mode;
|
||
#endif
|
||
|
||
PRMSG(2,"PTSOpenServer(%s)\n", port, 0,0 );
|
||
|
||
#if !defined(PTSNODENAME)
|
||
PRMSG(1,"PTSOpenServer: Protocol is not supported by a pts connection\n", 0,0,0);
|
||
return -1;
|
||
#else
|
||
if (port && *port ) {
|
||
if( *port == '/' ) { /* A full pathname */
|
||
(void) sprintf(server_path, "%s", port);
|
||
} else {
|
||
(void) sprintf(server_path, "%s%s", PTSNODENAME, port);
|
||
}
|
||
} else {
|
||
(void) sprintf(server_path, "%s%d", PTSNODENAME, getpid());
|
||
}
|
||
|
||
#ifdef HAS_STICKY_DIR_BIT
|
||
mode = 01777;
|
||
#else
|
||
mode = 0777;
|
||
#endif
|
||
if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
|
||
PRMSG (1, "PTSOpenServer: mkdir(%s) failed, errno = %d\n",
|
||
X_STREAMS_DIR, errno, 0);
|
||
return(-1);
|
||
}
|
||
|
||
#if 0
|
||
if( (fd=open(server_path, O_RDWR)) >= 0 ) {
|
||
/*
|
||
* This doesn't prevent the server from starting up, and doesn't
|
||
* prevent clients from trying to connect to the in-use PTS (which
|
||
* is often in use by something other than another server).
|
||
*/
|
||
PRMSG(1, "PTSOpenServer: A server is already running on port %s\n", port, 0,0 );
|
||
PRMSG(1, "PTSOpenServer: Remove %s if this is incorrect.\n", server_path, 0,0 );
|
||
close(fd);
|
||
return(-1);
|
||
}
|
||
#else
|
||
/* Just remove the old path (which is what happens with UNIXCONN) */
|
||
#endif
|
||
|
||
unlink(server_path);
|
||
|
||
if( (fd=open(DEV_PTMX, O_RDWR)) < 0) {
|
||
PRMSG(1, "PTSOpenServer: Unable to open %s\n", DEV_PTMX, 0,0 );
|
||
return(-1);
|
||
}
|
||
|
||
grantpt(fd);
|
||
unlockpt(fd);
|
||
|
||
if( (slave=ptsname(fd)) == NULL) {
|
||
PRMSG(1, "PTSOpenServer: Unable to get slave device name\n", 0,0,0 );
|
||
close(fd);
|
||
return(-1);
|
||
}
|
||
|
||
if( link(slave,server_path) < 0 ) {
|
||
PRMSG(1, "PTSOpenServer: Unable to link %s to %s\n", slave, server_path,0 );
|
||
close(fd);
|
||
return(-1);
|
||
}
|
||
|
||
if( chmod(server_path, 0666) < 0 ) {
|
||
PRMSG(1, "PTSOpenServer: Unable to chmod %s to 0666\n", server_path,0,0 );
|
||
close(fd);
|
||
return(-1);
|
||
}
|
||
|
||
if( (server=open(server_path, O_RDWR)) < 0 ) {
|
||
PRMSG(1, "PTSOpenServer: Unable to open server device %s\n", server_path,0,0 );
|
||
close(fd);
|
||
return(-1);
|
||
}
|
||
|
||
close(server);
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
|
||
{
|
||
PRMSG(1,"PTSOpenServer: failed to fill in addr info\n", 0, 0, 0);
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
return fd;
|
||
|
||
#endif /* !PTSNODENAME */
|
||
}
|
||
|
||
static int
|
||
TRANS(PTSAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
|
||
|
||
{
|
||
int newfd;
|
||
int in;
|
||
unsigned char length;
|
||
char buf[256];
|
||
struct sockaddr_un *sunaddr;
|
||
|
||
PRMSG(2,"PTSAccept(%x->%d)\n",ciptr,ciptr->fd,0);
|
||
|
||
if( (in=read(ciptr->fd,&length,1)) <= 0 ){
|
||
if( !in ) {
|
||
PRMSG(2,
|
||
"PTSAccept: Incoming connection closed\n",0,0,0);
|
||
}
|
||
else {
|
||
PRMSG(1,
|
||
"PTSAccept: Error reading incoming connection. errno=%d \n",
|
||
errno,0,0);
|
||
}
|
||
*status = TRANS_ACCEPT_MISC_ERROR;
|
||
return -1;
|
||
}
|
||
|
||
if( (in=read(ciptr->fd,buf,length)) <= 0 ){
|
||
if( !in ) {
|
||
PRMSG(2,
|
||
"PTSAccept: Incoming connection closed\n",0,0,0);
|
||
}
|
||
else {
|
||
PRMSG(1,
|
||
"PTSAccept: Error reading device name for new connection. errno=%d \n",
|
||
errno,0,0);
|
||
}
|
||
*status = TRANS_ACCEPT_MISC_ERROR;
|
||
return -1;
|
||
}
|
||
|
||
buf[length] = '\0';
|
||
|
||
if( (newfd=open(buf,O_RDWR)) < 0 ) {
|
||
PRMSG(1, "PTSAccept: Failed to open %s\n",buf,0,0);
|
||
*status = TRANS_ACCEPT_MISC_ERROR;
|
||
return -1;
|
||
}
|
||
|
||
write(newfd,"1",1);
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
newciptr->addrlen=ciptr->addrlen;
|
||
if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
|
||
PRMSG(1,"PTSAccept: failed to allocate memory for peer addr\n",
|
||
0,0,0);
|
||
close(newfd);
|
||
*status = TRANS_ACCEPT_BAD_MALLOC;
|
||
return -1;
|
||
}
|
||
|
||
memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
|
||
|
||
newciptr->peeraddrlen=sizeof(struct sockaddr_un);
|
||
if( (sunaddr=(struct sockaddr_un *)xalloc(newciptr->peeraddrlen)) == NULL ) {
|
||
PRMSG(1,"PTSAccept: failed to allocate memory for peer addr\n",
|
||
0,0,0);
|
||
xfree(newciptr->addr);
|
||
close(newfd);
|
||
*status = TRANS_ACCEPT_BAD_MALLOC;
|
||
return -1;
|
||
}
|
||
|
||
sunaddr->sun_family=AF_UNIX;
|
||
strcpy(sunaddr->sun_path,buf);
|
||
#if defined(BSD44SOCKETS)
|
||
sunaddr->sun_len=strlen(sunaddr->sun_path);
|
||
#endif
|
||
|
||
newciptr->peeraddr=(char *)sunaddr;
|
||
|
||
*status = 0;
|
||
|
||
return newfd;
|
||
}
|
||
|
||
#endif /* TRANS_SERVER */
|
||
#endif /* LOCAL_TRANS_PTS */
|
||
|
||
|
||
#ifdef LOCAL_TRANS_NAMED
|
||
|
||
/* NAMED */
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
static int
|
||
TRANS(NAMEDOpenClient)(XtransConnInfo ciptr, char *port)
|
||
|
||
{
|
||
#ifdef NAMEDNODENAME
|
||
int fd;
|
||
char server_path[64];
|
||
struct stat filestat;
|
||
# ifndef sun
|
||
extern int isastream(int);
|
||
# endif
|
||
#endif
|
||
|
||
PRMSG(2,"NAMEDOpenClient(%s)\n", port, 0,0 );
|
||
|
||
#if !defined(NAMEDNODENAME)
|
||
PRMSG(1,"NAMEDOpenClient: Protocol is not supported by a NAMED connection\n", 0,0,0);
|
||
return -1;
|
||
#else
|
||
if ( port && *port ) {
|
||
if( *port == '/' ) { /* A full pathname */
|
||
(void) snprintf(server_path, sizeof(server_path), "%s", port);
|
||
} else {
|
||
(void) snprintf(server_path, sizeof(server_path), "%s%s", NAMEDNODENAME, port);
|
||
}
|
||
} else {
|
||
(void) snprintf(server_path, sizeof(server_path), "%s%ld", NAMEDNODENAME, (long)getpid());
|
||
}
|
||
|
||
if ((fd = open(server_path, O_RDWR)) < 0) {
|
||
PRMSG(1,"NAMEDOpenClient: Cannot open %s for NAMED connection\n", server_path, 0,0 );
|
||
return -1;
|
||
}
|
||
|
||
if (fstat(fd, &filestat) < 0 ) {
|
||
PRMSG(1,"NAMEDOpenClient: Cannot stat %s for NAMED connection\n", server_path, 0,0 );
|
||
(void) close(fd);
|
||
return -1;
|
||
}
|
||
|
||
if ((filestat.st_mode & S_IFMT) != S_IFIFO) {
|
||
PRMSG(1,"NAMEDOpenClient: Device %s is not a FIFO\n", server_path, 0,0 );
|
||
/* Is this really a failure? */
|
||
(void) close(fd);
|
||
return -1;
|
||
}
|
||
|
||
|
||
if (isastream(fd) <= 0) {
|
||
PRMSG(1,"NAMEDOpenClient: %s is not a streams device\n", server_path, 0,0 );
|
||
(void) close(fd);
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
|
||
{
|
||
PRMSG(1,"NAMEDOpenClient: failed to fill in addr info\n",
|
||
0,0,0);
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
return(fd);
|
||
|
||
#endif /* !NAMEDNODENAME */
|
||
}
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
|
||
#ifdef NAMEDNODENAME
|
||
static int
|
||
TRANS(NAMEDOpenPipe)(const char *server_path)
|
||
{
|
||
PRMSG(2,"NAMEDOpenPipe(%s)\n", server_path, 0,0 );
|
||
|
||
int fd, pipefd[2];
|
||
struct stat sbuf;
|
||
int mode;
|
||
|
||
#if defined(sun) && defined(X11_t)
|
||
mode = 0775; /* Solaris requires uid or gid 0 to create X11 pipes */
|
||
#else
|
||
#ifdef HAS_STICKY_DIR_BIT
|
||
mode = 01777;
|
||
#else
|
||
mode = 0777;
|
||
#endif
|
||
#endif
|
||
if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
|
||
PRMSG (1, "NAMEDOpenPipe: mkdir(%s) failed, errno = %d\n",
|
||
X_STREAMS_DIR, errno, 0);
|
||
return(-1);
|
||
}
|
||
|
||
if(stat(server_path, &sbuf) != 0) {
|
||
if (errno == ENOENT) {
|
||
if ((fd = creat(server_path, (mode_t)0666)) == -1) {
|
||
PRMSG(1, "NAMEDOpenPipe: Can't open %s\n", server_path, 0,0 );
|
||
return(-1);
|
||
}
|
||
close(fd);
|
||
if (chmod(server_path, (mode_t)0666) < 0) {
|
||
PRMSG(1, "NAMEDOpenPipe: Can't open %s\n", server_path, 0,0 );
|
||
return(-1);
|
||
}
|
||
} else {
|
||
PRMSG(1, "NAMEDOpenPipe: stat on %s failed\n", server_path, 0,0 );
|
||
return(-1);
|
||
}
|
||
}
|
||
|
||
if( pipe(pipefd) != 0) {
|
||
PRMSG(1, "NAMEDOpenPipe: pipe() failed, errno=%d\n",errno, 0,0 );
|
||
return(-1);
|
||
}
|
||
|
||
if( ioctl(pipefd[0], I_PUSH, "connld") != 0) {
|
||
PRMSG(1, "NAMEDOpenPipe: ioctl(I_PUSH,\"connld\") failed, errno=%d\n",errno, 0,0 );
|
||
close(pipefd[0]);
|
||
close(pipefd[1]);
|
||
return(-1);
|
||
}
|
||
|
||
if( fattach(pipefd[0], server_path) != 0) {
|
||
PRMSG(1, "NAMEDOpenPipe: fattach(%s) failed, errno=%d\n", server_path,errno, 0 );
|
||
close(pipefd[0]);
|
||
close(pipefd[1]);
|
||
return(-1);
|
||
}
|
||
|
||
return(pipefd[1]);
|
||
}
|
||
#endif
|
||
|
||
static int
|
||
TRANS(NAMEDOpenServer)(XtransConnInfo ciptr, char *port)
|
||
{
|
||
#ifdef NAMEDNODENAME
|
||
int fd;
|
||
char server_path[64];
|
||
#endif
|
||
|
||
PRMSG(2,"NAMEDOpenServer(%s)\n", port, 0,0 );
|
||
|
||
#if !defined(NAMEDNODENAME)
|
||
PRMSG(1,"NAMEDOpenServer: Protocol is not supported by a NAMED connection\n", 0,0,0);
|
||
return -1;
|
||
#else
|
||
if ( port && *port ) {
|
||
if( *port == '/' ) { /* A full pathname */
|
||
(void) snprintf(server_path, sizeof(server_path), "%s", port);
|
||
} else {
|
||
(void) snprintf(server_path, sizeof(server_path), "%s%s",
|
||
NAMEDNODENAME, port);
|
||
}
|
||
} else {
|
||
(void) snprintf(server_path, sizeof(server_path), "%s%ld",
|
||
NAMEDNODENAME, (long)getpid());
|
||
}
|
||
|
||
fd = TRANS(NAMEDOpenPipe)(server_path);
|
||
if (fd < 0) {
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
|
||
{
|
||
PRMSG(1,"NAMEDOpenServer: failed to fill in addr info\n", 0,0,0);
|
||
TRANS(LocalClose)(ciptr);
|
||
return -1;
|
||
}
|
||
|
||
return fd;
|
||
|
||
#endif /* !NAMEDNODENAME */
|
||
}
|
||
|
||
static int
|
||
TRANS(NAMEDResetListener) (XtransConnInfo ciptr)
|
||
|
||
{
|
||
int status = TRANS_RESET_NOOP;
|
||
struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr;
|
||
struct stat statb;
|
||
|
||
PRMSG(2,"NAMEDResetListener(%p, %d)\n", ciptr, ciptr->fd, 0 );
|
||
|
||
if (ciptr->fd != -1) {
|
||
/*
|
||
* see if the pipe has disappeared
|
||
*/
|
||
|
||
if (stat (sockname->sun_path, &statb) == -1 ||
|
||
(statb.st_mode & S_IFMT) != S_IFIFO) {
|
||
PRMSG(3, "Pipe %s trashed, recreating\n", sockname->sun_path, 0, 0);
|
||
TRANS(LocalClose)(ciptr);
|
||
ciptr->fd = TRANS(NAMEDOpenPipe)(sockname->sun_path);
|
||
if (ciptr->fd >= 0)
|
||
return TRANS_RESET_NEW_FD;
|
||
else
|
||
return TRANS_CREATE_LISTENER_FAILED;
|
||
}
|
||
}
|
||
return TRANS_RESET_NOOP;
|
||
}
|
||
|
||
static int
|
||
TRANS(NAMEDAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
|
||
|
||
{
|
||
struct strrecvfd str;
|
||
|
||
PRMSG(2,"NAMEDAccept(%x->%d)\n", ciptr, ciptr->fd, 0 );
|
||
|
||
if( ioctl(ciptr->fd, I_RECVFD, &str ) < 0 ) {
|
||
PRMSG(1, "NAMEDAccept: ioctl(I_RECVFD) failed, errno=%d\n", errno, 0,0 );
|
||
*status = TRANS_ACCEPT_MISC_ERROR;
|
||
return(-1);
|
||
}
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
newciptr->family=ciptr->family;
|
||
newciptr->addrlen=ciptr->addrlen;
|
||
if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
|
||
PRMSG(1,
|
||
"NAMEDAccept: failed to allocate memory for pipe addr\n",
|
||
0,0,0);
|
||
close(str.fd);
|
||
*status = TRANS_ACCEPT_BAD_MALLOC;
|
||
return -1;
|
||
}
|
||
|
||
memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
|
||
|
||
newciptr->peeraddrlen=newciptr->addrlen;
|
||
if( (newciptr->peeraddr=(char *)xalloc(newciptr->peeraddrlen)) == NULL ) {
|
||
PRMSG(1,
|
||
"NAMEDAccept: failed to allocate memory for peer addr\n",
|
||
0,0,0);
|
||
xfree(newciptr->addr);
|
||
close(str.fd);
|
||
*status = TRANS_ACCEPT_BAD_MALLOC;
|
||
return -1;
|
||
}
|
||
|
||
memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
|
||
|
||
*status = 0;
|
||
|
||
return str.fd;
|
||
}
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
#endif /* LOCAL_TRANS_NAMED */
|
||
|
||
|
||
|
||
#if defined(LOCAL_TRANS_SCO)
|
||
|
||
/*
|
||
* connect_spipe is used by the SCO and ISC connection types.
|
||
*/
|
||
static int
|
||
connect_spipe(int fd1, int fd2)
|
||
{
|
||
long temp;
|
||
struct strfdinsert sbuf;
|
||
|
||
sbuf.databuf.maxlen = -1;
|
||
sbuf.databuf.len = -1;
|
||
sbuf.databuf.buf = NULL;
|
||
sbuf.ctlbuf.maxlen = sizeof(long);
|
||
sbuf.ctlbuf.len = sizeof(long);
|
||
sbuf.ctlbuf.buf = (caddr_t)&temp;
|
||
sbuf.offset = 0;
|
||
sbuf.fildes = fd2;
|
||
sbuf.flags = 0;
|
||
|
||
if( ioctl(fd1, I_FDINSERT, &sbuf) < 0 )
|
||
return(-1);
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* named_spipe is used by the SCO and ISC connection types.
|
||
*/
|
||
|
||
static int
|
||
named_spipe(int fd, char *path)
|
||
|
||
{
|
||
int oldUmask, ret;
|
||
struct stat sbuf;
|
||
|
||
oldUmask = umask(0);
|
||
|
||
(void) fstat(fd, &sbuf);
|
||
ret = mknod(path, 0020666, sbuf.st_rdev);
|
||
|
||
umask(oldUmask);
|
||
|
||
if (ret < 0) {
|
||
ret = -1;
|
||
} else {
|
||
ret = fd;
|
||
}
|
||
|
||
return(ret);
|
||
}
|
||
|
||
#endif /* defined(LOCAL_TRANS_SCO) */
|
||
|
||
|
||
|
||
|
||
#ifdef LOCAL_TRANS_SCO
|
||
/* SCO */
|
||
|
||
/*
|
||
* 2002-11-09 (jkj@sco.com)
|
||
*
|
||
* This code has been modified to match what is in the actual SCO X server.
|
||
* This greatly helps inter-operability between X11R6 and X11R5 (the native
|
||
* SCO server). Mainly, it relies on streams nodes existing in /dev, not
|
||
* creating them or unlinking them, which breaks the native X server.
|
||
*
|
||
* However, this is only for the X protocol. For all other protocols, we
|
||
* do in fact create the nodes, as only X11R6 will use them, and this makes
|
||
* it possible to have both types of clients running, otherwise we get all
|
||
* kinds of nasty errors on startup for anything that doesnt use the X
|
||
* protocol (like SM, when KDE starts up).
|
||
*/
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
static int
|
||
TRANS(SCOOpenClient)(XtransConnInfo ciptr, char *port)
|
||
{
|
||
#ifdef SCORNODENAME
|
||
int fd, server, fl, ret;
|
||
char server_path[64];
|
||
struct strbuf ctlbuf;
|
||
unsigned long alarm_time;
|
||
void (*savef)();
|
||
long temp;
|
||
extern int getmsg(), putmsg();
|
||
#endif
|
||
|
||
PRMSG(2,"SCOOpenClient(%s)\n", port, 0,0 );
|
||
if (!port || !port[0])
|
||
port = "0";
|
||
|
||
#if !defined(SCORNODENAME)
|
||
PRMSG(2,"SCOOpenClient: Protocol is not supported by a SCO connection\n", 0,0,0);
|
||
return -1;
|
||
#else
|
||
(void) sprintf(server_path, SCORNODENAME, port);
|
||
|
||
if ((server = open(server_path, O_RDWR)) < 0) {
|
||
PRMSG(1,"SCOOpenClient: failed to open %s\n", server_path, 0,0 );
|
||
return -1;
|
||
}
|
||
|
||
if ((fd = open(DEV_SPX, O_RDWR)) < 0) {
|
||
PRMSG(1,"SCOOpenClient: failed to open %s\n", DEV_SPX, 0,0 );
|
||
close(server);
|
||
return -1;
|
||
}
|
||
|
||
(void) write(server, &server, 1);
|
||
ctlbuf.len = 0;
|
||
ctlbuf.maxlen = sizeof(long);
|
||
ctlbuf.buf = (caddr_t)&temp;
|
||
fl = 0;
|
||
|
||
savef = signal(SIGALRM, _dummy);
|
||
alarm_time = alarm(10);
|
||
|
||
ret = getmsg(server, &ctlbuf, 0, &fl);
|
||
|
||
(void) alarm(alarm_time);
|
||
(void) signal(SIGALRM, savef);
|
||
|
||
if (ret < 0) {
|
||
PRMSG(1,"SCOOpenClient: error from getmsg\n", 0,0,0 );
|
||
close(fd);
|
||
close(server);
|
||
return -1;
|
||
}
|
||
|
||
/* The msg we got via getmsg is the result of an
|
||
* I_FDINSERT, so if we do a putmsg with whatever
|
||
* we recieved, we're doing another I_FDINSERT ...
|
||
*/
|
||
(void) putmsg(fd, &ctlbuf, 0, 0);
|
||
(void) fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NDELAY);
|
||
|
||
(void) close(server);
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
#if defined(X11_t) && defined(__SCO__)
|
||
ciptr->flags |= TRANS_NOUNLINK;
|
||
#endif
|
||
if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
|
||
{
|
||
PRMSG(1,"SCOOpenClient: failed to fill addr info\n", 0, 0, 0);
|
||
close(fd);
|
||
return -1;
|
||
}
|
||
|
||
return(fd);
|
||
|
||
#endif /* !SCORNODENAME */
|
||
}
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
static int
|
||
TRANS(SCOOpenServer)(XtransConnInfo ciptr, char *port)
|
||
{
|
||
#ifdef SCORNODENAME
|
||
char serverR_path[64];
|
||
char serverS_path[64];
|
||
struct flock mylock;
|
||
int fdr = -1;
|
||
int fds = -1;
|
||
#endif
|
||
|
||
PRMSG(2,"SCOOpenServer(%s)\n", port, 0,0 );
|
||
if (!port || !port[0])
|
||
port = "0";
|
||
|
||
#if !defined(SCORNODENAME)
|
||
PRMSG(1,"SCOOpenServer: Protocol is not supported by a SCO connection\n", 0,0,0);
|
||
return -1;
|
||
#else
|
||
(void) sprintf(serverR_path, SCORNODENAME, port);
|
||
(void) sprintf(serverS_path, SCOSNODENAME, port);
|
||
|
||
#if !defined(X11_t) || !defined(__SCO__)
|
||
unlink(serverR_path);
|
||
unlink(serverS_path);
|
||
|
||
if ((fds = open(DEV_SPX, O_RDWR)) < 0 ||
|
||
(fdr = open(DEV_SPX, O_RDWR)) < 0 ) {
|
||
PRMSG(1,"SCOOpenServer: failed to open %s\n", DEV_SPX, 0,0 );
|
||
return -1;
|
||
}
|
||
|
||
if (named_spipe (fds, serverS_path) == -1) {
|
||
PRMSG(1,"SCOOpenServer: failed to create %s\n", serverS_path, 0, 0);
|
||
close (fdr);
|
||
close (fds);
|
||
return -1;
|
||
}
|
||
|
||
if (named_spipe (fdr, serverR_path) == -1) {
|
||
PRMSG(1,"SCOOpenServer: failed to create %s\n", serverR_path, 0, 0);
|
||
close (fdr);
|
||
close (fds);
|
||
return -1;
|
||
}
|
||
#else /* X11_t */
|
||
|
||
fds = open (serverS_path, O_RDWR | O_NDELAY);
|
||
if (fds < 0) {
|
||
PRMSG(1,"SCOOpenServer: failed to open %s\n", serverS_path, 0, 0);
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* Lock the connection device for the duration of the server.
|
||
* This resolves multiple server starts especially on SMP machines.
|
||
*/
|
||
mylock.l_type = F_WRLCK;
|
||
mylock.l_whence = 0;
|
||
mylock.l_start = 0;
|
||
mylock.l_len = 0;
|
||
if (fcntl (fds, F_SETLK, &mylock) < 0) {
|
||
PRMSG(1,"SCOOpenServer: failed to lock %s\n", serverS_path, 0, 0);
|
||
close (fds);
|
||
return -1;
|
||
}
|
||
|
||
fdr = open (serverR_path, O_RDWR | O_NDELAY);
|
||
if (fds < 0) {
|
||
PRMSG(1,"SCOOpenServer: failed to open %s\n", serverR_path, 0, 0);
|
||
close (fds);
|
||
return -1;
|
||
}
|
||
#endif /* X11_t */
|
||
|
||
if (connect_spipe(fds, fdr)) {
|
||
PRMSG(1,"SCOOpenServer: ioctl(I_FDINSERT) failed on %s\n",
|
||
serverS_path, 0, 0);
|
||
close (fdr);
|
||
close (fds);
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
#if defined(X11_t) && defined(__SCO__)
|
||
ciptr->flags |= TRANS_NOUNLINK;
|
||
#endif
|
||
if (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0) {
|
||
PRMSG(1,"SCOOpenServer: failed to fill in addr info\n", 0,0,0);
|
||
close(fds);
|
||
close(fdr);
|
||
return -1;
|
||
}
|
||
|
||
return(fds);
|
||
|
||
#endif /* !SCORNODENAME */
|
||
}
|
||
|
||
static int
|
||
TRANS(SCOAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
|
||
{
|
||
char c;
|
||
int fd;
|
||
|
||
PRMSG(2,"SCOAccept(%d)\n", ciptr->fd, 0,0 );
|
||
|
||
if (read(ciptr->fd, &c, 1) < 0) {
|
||
PRMSG(1,"SCOAccept: can't read from client\n",0,0,0);
|
||
*status = TRANS_ACCEPT_MISC_ERROR;
|
||
return(-1);
|
||
}
|
||
|
||
if( (fd = open(DEV_SPX, O_RDWR)) < 0 ) {
|
||
PRMSG(1,"SCOAccept: can't open \"%s\"\n",DEV_SPX, 0,0 );
|
||
*status = TRANS_ACCEPT_MISC_ERROR;
|
||
return(-1);
|
||
}
|
||
|
||
if (connect_spipe (ciptr->fd, fd) < 0) {
|
||
PRMSG(1,"SCOAccept: ioctl(I_FDINSERT) failed\n", 0, 0, 0);
|
||
close (fd);
|
||
*status = TRANS_ACCEPT_MISC_ERROR;
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* Everything looks good: fill in the XtransConnInfo structure.
|
||
*/
|
||
|
||
newciptr->addrlen=ciptr->addrlen;
|
||
if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
|
||
PRMSG(1,
|
||
"SCOAccept: failed to allocate memory for peer addr\n",
|
||
0,0,0);
|
||
close(fd);
|
||
*status = TRANS_ACCEPT_BAD_MALLOC;
|
||
return -1;
|
||
}
|
||
|
||
memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
|
||
#if defined(__SCO__)
|
||
newciptr->flags |= TRANS_NOUNLINK;
|
||
#endif
|
||
|
||
newciptr->peeraddrlen=newciptr->addrlen;
|
||
if( (newciptr->peeraddr=(char *)xalloc(newciptr->peeraddrlen)) == NULL ) {
|
||
PRMSG(1,
|
||
"SCOAccept: failed to allocate memory for peer addr\n",
|
||
0,0,0);
|
||
xfree(newciptr->addr);
|
||
close(fd);
|
||
*status = TRANS_ACCEPT_BAD_MALLOC;
|
||
return -1;
|
||
}
|
||
|
||
memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
|
||
|
||
*status = 0;
|
||
|
||
return(fd);
|
||
}
|
||
|
||
#endif /* TRANS_SERVER */
|
||
#endif /* LOCAL_TRANS_SCO */
|
||
|
||
|
||
|
||
#ifdef TRANS_REOPEN
|
||
#ifdef LOCAL_TRANS_PTS
|
||
|
||
static int
|
||
TRANS(PTSReopenServer)(XtransConnInfo ciptr, int fd, char *port)
|
||
|
||
{
|
||
#ifdef PTSNODENAME
|
||
char server_path[64];
|
||
#endif
|
||
|
||
PRMSG(2,"PTSReopenServer(%d,%s)\n", fd, port, 0 );
|
||
|
||
#if !defined(PTSNODENAME)
|
||
PRMSG(1,"PTSReopenServer: Protocol is not supported by a pts connection\n", 0,0,0);
|
||
return 0;
|
||
#else
|
||
if (port && *port ) {
|
||
if( *port == '/' ) { /* A full pathname */
|
||
(void) sprintf(server_path, "%s", port);
|
||
} else {
|
||
(void) sprintf(server_path, "%s%s", PTSNODENAME, port);
|
||
}
|
||
} else {
|
||
(void) sprintf(server_path, "%s%ld", PTSNODENAME, (long)getpid());
|
||
}
|
||
|
||
if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
|
||
{
|
||
PRMSG(1,"PTSReopenServer: failed to fill in addr info\n",
|
||
0,0,0);
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
|
||
#endif /* !PTSNODENAME */
|
||
}
|
||
|
||
#endif /* LOCAL_TRANS_PTS */
|
||
|
||
#ifdef LOCAL_TRANS_NAMED
|
||
|
||
static int
|
||
TRANS(NAMEDReopenServer)(XtransConnInfo ciptr, int fd, char *port)
|
||
|
||
{
|
||
#ifdef NAMEDNODENAME
|
||
char server_path[64];
|
||
#endif
|
||
|
||
PRMSG(2,"NAMEDReopenServer(%s)\n", port, 0,0 );
|
||
|
||
#if !defined(NAMEDNODENAME)
|
||
PRMSG(1,"NAMEDReopenServer: Protocol is not supported by a NAMED connection\n", 0,0,0);
|
||
return 0;
|
||
#else
|
||
if ( port && *port ) {
|
||
if( *port == '/' ) { /* A full pathname */
|
||
(void) sprintf(server_path, "%s", port);
|
||
} else {
|
||
(void) sprintf(server_path, "%s%s", NAMEDNODENAME, port);
|
||
}
|
||
} else {
|
||
(void) sprintf(server_path, "%s%ld", NAMEDNODENAME, (long)getpid());
|
||
}
|
||
|
||
if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
|
||
{
|
||
PRMSG(1,"NAMEDReopenServer: failed to fill in addr info\n",
|
||
0,0,0);
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
|
||
#endif /* !NAMEDNODENAME */
|
||
}
|
||
|
||
#endif /* LOCAL_TRANS_NAMED */
|
||
|
||
|
||
#ifdef LOCAL_TRANS_SCO
|
||
static int
|
||
TRANS(SCOReopenServer)(XtransConnInfo ciptr, int fd, char *port)
|
||
|
||
{
|
||
#ifdef SCORNODENAME
|
||
char serverR_path[64], serverS_path[64];
|
||
#endif
|
||
|
||
PRMSG(2,"SCOReopenServer(%s)\n", port, 0,0 );
|
||
if (!port || !port[0])
|
||
port = "0";
|
||
|
||
#if !defined(SCORNODENAME)
|
||
PRMSG(2,"SCOReopenServer: Protocol is not supported by a SCO connection\n", 0,0,0);
|
||
return 0;
|
||
#else
|
||
(void) sprintf(serverR_path, SCORNODENAME, port);
|
||
(void) sprintf(serverS_path, SCOSNODENAME, port);
|
||
|
||
#if defined(X11_t) && defined(__SCO__)
|
||
ciptr->flags |= TRANS_NOUNLINK;
|
||
#endif
|
||
if (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0)
|
||
{
|
||
PRMSG(1, "SCOReopenServer: failed to fill in addr info\n", 0,0,0);
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
|
||
#endif /* SCORNODENAME */
|
||
}
|
||
|
||
#endif /* LOCAL_TRANS_SCO */
|
||
|
||
#endif /* TRANS_REOPEN */
|
||
|
||
|
||
|
||
/*
|
||
* This table contains all of the entry points for the different local
|
||
* connection mechanisms.
|
||
*/
|
||
|
||
typedef struct _LOCALtrans2dev {
|
||
char *transname;
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
int (*devcotsopenclient)(
|
||
XtransConnInfo, char * /*port*/
|
||
);
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
int (*devcotsopenserver)(
|
||
XtransConnInfo, char * /*port*/
|
||
);
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
int (*devcltsopenclient)(
|
||
XtransConnInfo, char * /*port*/
|
||
);
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
int (*devcltsopenserver)(
|
||
XtransConnInfo, char * /*port*/
|
||
);
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
#ifdef TRANS_REOPEN
|
||
|
||
int (*devcotsreopenserver)(
|
||
XtransConnInfo,
|
||
int, /* fd */
|
||
char * /* port */
|
||
);
|
||
|
||
int (*devcltsreopenserver)(
|
||
XtransConnInfo,
|
||
int, /* fd */
|
||
char * /* port */
|
||
);
|
||
|
||
#endif /* TRANS_REOPEN */
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
int (*devreset)(
|
||
XtransConnInfo /* ciptr */
|
||
);
|
||
|
||
int (*devaccept)(
|
||
XtransConnInfo, XtransConnInfo, int *
|
||
);
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
} LOCALtrans2dev;
|
||
|
||
static LOCALtrans2dev LOCALtrans2devtab[] = {
|
||
#ifdef LOCAL_TRANS_PTS
|
||
{"",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(PTSOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(PTSOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(PTSReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
NULL, /* ResetListener */
|
||
TRANS(PTSAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
|
||
{"local",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(PTSOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(PTSOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(PTSReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
NULL, /* ResetListener */
|
||
TRANS(PTSAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
|
||
{"pts",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(PTSOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(PTSOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(PTSReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
NULL, /* ResetListener */
|
||
TRANS(PTSAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
#else /* !LOCAL_TRANS_PTS */
|
||
{"",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(NAMEDOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(NAMEDReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDResetListener),
|
||
TRANS(NAMEDAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
|
||
{"local",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(NAMEDOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(NAMEDReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDResetListener),
|
||
TRANS(NAMEDAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
#endif /* !LOCAL_TRANS_PTS */
|
||
|
||
#ifdef LOCAL_TRANS_NAMED
|
||
{"named",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(NAMEDOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(NAMEDReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDResetListener),
|
||
TRANS(NAMEDAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
|
||
#ifdef sun /* Alias "pipe" to named, since that's what Solaris called it */
|
||
{"pipe",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(NAMEDOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(NAMEDReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
TRANS(NAMEDResetListener),
|
||
TRANS(NAMEDAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
#endif /* sun */
|
||
#endif /* LOCAL_TRANS_NAMED */
|
||
|
||
|
||
#ifdef LOCAL_TRANS_SCO
|
||
{"sco",
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(SCOOpenClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(SCOOpenServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(OpenFail),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(SCOReopenServer),
|
||
TRANS(ReopenFail),
|
||
#endif
|
||
#ifdef TRANS_SERVER
|
||
NULL, /* ResetListener */
|
||
TRANS(SCOAccept)
|
||
#endif /* TRANS_SERVER */
|
||
},
|
||
#endif /* LOCAL_TRANS_SCO */
|
||
};
|
||
|
||
#define NUMTRANSPORTS (sizeof(LOCALtrans2devtab)/sizeof(LOCALtrans2dev))
|
||
|
||
static char *XLOCAL=NULL;
|
||
static char *workingXLOCAL=NULL;
|
||
static char *freeXLOCAL=NULL;
|
||
|
||
#if defined(__SCO__)
|
||
#define DEF_XLOCAL "SCO:UNIX:PTS"
|
||
#elif defined(__UNIXWARE__)
|
||
#define DEF_XLOCAL "UNIX:PTS:NAMED:SCO"
|
||
#elif defined(sun)
|
||
#define DEF_XLOCAL "UNIX:NAMED"
|
||
#else
|
||
#define DEF_XLOCAL "UNIX:PTS:NAMED:ISC:SCO"
|
||
#endif
|
||
|
||
static void
|
||
TRANS(LocalInitTransports)(char *protocol)
|
||
|
||
{
|
||
PRMSG(3,"LocalInitTransports(%s)\n", protocol, 0,0 );
|
||
|
||
if( strcmp(protocol,"local") && strcmp(protocol,"LOCAL") )
|
||
{
|
||
workingXLOCAL=freeXLOCAL=(char *)xalloc (strlen (protocol) + 1);
|
||
if (workingXLOCAL)
|
||
strcpy (workingXLOCAL, protocol);
|
||
}
|
||
else {
|
||
XLOCAL=(char *)getenv("XLOCAL");
|
||
if(XLOCAL==NULL)
|
||
XLOCAL=DEF_XLOCAL;
|
||
workingXLOCAL=freeXLOCAL=(char *)xalloc (strlen (XLOCAL) + 1);
|
||
if (workingXLOCAL)
|
||
strcpy (workingXLOCAL, XLOCAL);
|
||
}
|
||
}
|
||
|
||
static void
|
||
TRANS(LocalEndTransports)(void)
|
||
|
||
{
|
||
PRMSG(3,"LocalEndTransports()\n", 0,0,0 );
|
||
xfree(freeXLOCAL);
|
||
}
|
||
|
||
#define TYPEBUFSIZE 32
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
static LOCALtrans2dev *
|
||
TRANS(LocalGetNextTransport)(void)
|
||
|
||
{
|
||
int i,j;
|
||
char *typetocheck;
|
||
char typebuf[TYPEBUFSIZE];
|
||
PRMSG(3,"LocalGetNextTransport()\n", 0,0,0 );
|
||
|
||
while(1)
|
||
{
|
||
if( workingXLOCAL == NULL || *workingXLOCAL == '\0' )
|
||
return NULL;
|
||
|
||
typetocheck=workingXLOCAL;
|
||
workingXLOCAL=strchr(workingXLOCAL,':');
|
||
if(workingXLOCAL && *workingXLOCAL)
|
||
*workingXLOCAL++='\0';
|
||
|
||
for(i=0;i<NUMTRANSPORTS;i++)
|
||
{
|
||
/*
|
||
* This is equivalent to a case insensitive strcmp(),
|
||
* but should be more portable.
|
||
*/
|
||
strncpy(typebuf,typetocheck,TYPEBUFSIZE);
|
||
for(j=0;j<TYPEBUFSIZE;j++)
|
||
if (isupper(typebuf[j]))
|
||
typebuf[j]=tolower(typebuf[j]);
|
||
|
||
/* Now, see if they match */
|
||
if(!strcmp(LOCALtrans2devtab[i].transname,typebuf))
|
||
return &LOCALtrans2devtab[i];
|
||
}
|
||
}
|
||
#if 0
|
||
/*NOTREACHED*/
|
||
return NULL;
|
||
#endif
|
||
}
|
||
|
||
#ifdef NEED_UTSNAME
|
||
#include <sys/utsname.h>
|
||
#endif
|
||
|
||
/*
|
||
* Make sure 'host' is really local.
|
||
*/
|
||
|
||
static int
|
||
HostReallyLocal (char *host)
|
||
|
||
{
|
||
/*
|
||
* The 'host' passed to this function may have been generated
|
||
* by either uname() or gethostname(). We try both if possible.
|
||
*/
|
||
|
||
#ifdef NEED_UTSNAME
|
||
struct utsname name;
|
||
#endif
|
||
char buf[256];
|
||
|
||
#ifdef NEED_UTSNAME
|
||
if (uname (&name) >= 0 && strcmp (host, name.nodename) == 0)
|
||
return (1);
|
||
#endif
|
||
|
||
buf[0] = '\0';
|
||
(void) gethostname (buf, 256);
|
||
buf[255] = '\0';
|
||
|
||
if (strcmp (host, buf) == 0)
|
||
return (1);
|
||
|
||
return (0);
|
||
}
|
||
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalOpenClient)(int type, char *protocol, char *host, char *port)
|
||
|
||
{
|
||
LOCALtrans2dev *transptr;
|
||
XtransConnInfo ciptr;
|
||
int index;
|
||
|
||
PRMSG(3,"LocalOpenClient()\n", 0,0,0 );
|
||
|
||
/*
|
||
* Make sure 'host' is really local. If not, we return failure.
|
||
* The reason we make this check is because a process may advertise
|
||
* a "local" address for which it can accept connections, but if a
|
||
* process on a remote machine tries to connect to this address,
|
||
* we know for sure it will fail.
|
||
*/
|
||
|
||
if (strcmp (host, "unix") != 0 && !HostReallyLocal (host))
|
||
{
|
||
PRMSG (1,
|
||
"LocalOpenClient: Cannot connect to non-local host %s\n",
|
||
host, 0, 0);
|
||
return NULL;
|
||
}
|
||
|
||
|
||
#if defined(X11_t)
|
||
/*
|
||
* X has a well known port, that is transport dependant. It is easier
|
||
* to handle it here, than try and come up with a transport independent
|
||
* representation that can be passed in and resolved the usual way.
|
||
*
|
||
* The port that is passed here is really a string containing the idisplay
|
||
* from ConnectDisplay(). Since that is what we want for the local transports,
|
||
* we don't have to do anything special.
|
||
*/
|
||
#endif /* X11_t */
|
||
|
||
if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
|
||
{
|
||
PRMSG(1,"LocalOpenClient: calloc(1,%d) failed\n",
|
||
sizeof(struct _XtransConnInfo),0,0 );
|
||
return NULL;
|
||
}
|
||
|
||
ciptr->fd = -1;
|
||
|
||
TRANS(LocalInitTransports)(protocol);
|
||
|
||
index = 0;
|
||
for(transptr=TRANS(LocalGetNextTransport)();
|
||
transptr!=NULL;transptr=TRANS(LocalGetNextTransport)(), index++)
|
||
{
|
||
switch( type )
|
||
{
|
||
case XTRANS_OPEN_COTS_CLIENT:
|
||
ciptr->fd=transptr->devcotsopenclient(ciptr,port);
|
||
break;
|
||
case XTRANS_OPEN_CLTS_CLIENT:
|
||
ciptr->fd=transptr->devcltsopenclient(ciptr,port);
|
||
break;
|
||
case XTRANS_OPEN_COTS_SERVER:
|
||
case XTRANS_OPEN_CLTS_SERVER:
|
||
PRMSG(1,
|
||
"LocalOpenClient: Should not be opening a server with this function\n",
|
||
0,0,0);
|
||
break;
|
||
default:
|
||
PRMSG(1,
|
||
"LocalOpenClient: Unknown Open type %d\n",
|
||
type, 0,0 );
|
||
}
|
||
if( ciptr->fd >= 0 )
|
||
break;
|
||
}
|
||
|
||
TRANS(LocalEndTransports)();
|
||
|
||
if( ciptr->fd < 0 )
|
||
{
|
||
xfree(ciptr);
|
||
return NULL;
|
||
}
|
||
|
||
ciptr->priv=(char *)transptr;
|
||
ciptr->index = index;
|
||
|
||
return ciptr;
|
||
}
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalOpenServer)(int type, char *protocol, char *host, char *port)
|
||
|
||
{
|
||
int i;
|
||
XtransConnInfo ciptr;
|
||
|
||
PRMSG(2,"LocalOpenServer(%d,%s,%s)\n", type, protocol, port);
|
||
|
||
#if defined(X11_t)
|
||
/*
|
||
* For X11, the port will be in the format xserverN where N is the
|
||
* display number. All of the local connections just need to know
|
||
* the display number because they don't do any name resolution on
|
||
* the port. This just truncates port to the display portion.
|
||
*/
|
||
#endif /* X11_t */
|
||
|
||
if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
|
||
{
|
||
PRMSG(1,"LocalOpenServer: calloc(1,%d) failed\n",
|
||
sizeof(struct _XtransConnInfo),0,0 );
|
||
return NULL;
|
||
}
|
||
|
||
for(i=1;i<NUMTRANSPORTS;i++)
|
||
{
|
||
if( strcmp(protocol,LOCALtrans2devtab[i].transname) != 0 )
|
||
continue;
|
||
switch( type )
|
||
{
|
||
case XTRANS_OPEN_COTS_CLIENT:
|
||
case XTRANS_OPEN_CLTS_CLIENT:
|
||
PRMSG(1,
|
||
"LocalOpenServer: Should not be opening a client with this function\n",
|
||
0,0,0);
|
||
break;
|
||
case XTRANS_OPEN_COTS_SERVER:
|
||
ciptr->fd=LOCALtrans2devtab[i].devcotsopenserver(ciptr,port);
|
||
break;
|
||
case XTRANS_OPEN_CLTS_SERVER:
|
||
ciptr->fd=LOCALtrans2devtab[i].devcltsopenserver(ciptr,port);
|
||
break;
|
||
default:
|
||
PRMSG(1,"LocalOpenServer: Unknown Open type %d\n",
|
||
type ,0,0);
|
||
}
|
||
if( ciptr->fd >= 0 ) {
|
||
ciptr->priv=(char *)&LOCALtrans2devtab[i];
|
||
ciptr->index=i;
|
||
ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
|
||
return ciptr;
|
||
}
|
||
}
|
||
|
||
xfree(ciptr);
|
||
return NULL;
|
||
}
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
|
||
#ifdef TRANS_REOPEN
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalReopenServer)(int type, int index, int fd, char *port)
|
||
|
||
{
|
||
XtransConnInfo ciptr;
|
||
int stat = 0;
|
||
|
||
PRMSG(2,"LocalReopenServer(%d,%d,%d)\n", type, index, fd);
|
||
|
||
if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
|
||
{
|
||
PRMSG(1,"LocalReopenServer: calloc(1,%d) failed\n",
|
||
sizeof(struct _XtransConnInfo),0,0 );
|
||
return NULL;
|
||
}
|
||
|
||
ciptr->fd = fd;
|
||
|
||
switch( type )
|
||
{
|
||
case XTRANS_OPEN_COTS_SERVER:
|
||
stat = LOCALtrans2devtab[index].devcotsreopenserver(ciptr,fd,port);
|
||
break;
|
||
case XTRANS_OPEN_CLTS_SERVER:
|
||
stat = LOCALtrans2devtab[index].devcltsreopenserver(ciptr,fd,port);
|
||
break;
|
||
default:
|
||
PRMSG(1,"LocalReopenServer: Unknown Open type %d\n",
|
||
type ,0,0);
|
||
}
|
||
|
||
if( stat > 0 ) {
|
||
ciptr->priv=(char *)&LOCALtrans2devtab[index];
|
||
ciptr->index=index;
|
||
ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
|
||
return ciptr;
|
||
}
|
||
|
||
xfree(ciptr);
|
||
return NULL;
|
||
}
|
||
|
||
#endif /* TRANS_REOPEN */
|
||
|
||
|
||
|
||
/*
|
||
* This is the Local implementation of the X Transport service layer
|
||
*/
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalOpenCOTSClient)(Xtransport *thistrans, char *protocol,
|
||
char *host, char *port)
|
||
|
||
{
|
||
PRMSG(2,"LocalOpenCOTSClient(%s,%s,%s)\n",protocol,host,port);
|
||
|
||
return TRANS(LocalOpenClient)(XTRANS_OPEN_COTS_CLIENT, protocol, host, port);
|
||
}
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalOpenCOTSServer)(Xtransport *thistrans, char *protocol,
|
||
char *host, char *port)
|
||
|
||
{
|
||
char *typetocheck = NULL;
|
||
int found = 0;
|
||
char typebuf[TYPEBUFSIZE];
|
||
|
||
PRMSG(2,"LocalOpenCOTSServer(%s,%s,%s)\n",protocol,host,port);
|
||
|
||
/* Check if this local type is in the XLOCAL list */
|
||
TRANS(LocalInitTransports)("local");
|
||
typetocheck = workingXLOCAL;
|
||
while (typetocheck && !found) {
|
||
int j;
|
||
|
||
workingXLOCAL = strchr(workingXLOCAL, ':');
|
||
if (workingXLOCAL && *workingXLOCAL)
|
||
*workingXLOCAL++ = '\0';
|
||
strncpy(typebuf, typetocheck, TYPEBUFSIZE);
|
||
for (j = 0; j < TYPEBUFSIZE; j++)
|
||
if (isupper(typebuf[j]))
|
||
typebuf[j] = tolower(typebuf[j]);
|
||
if (!strcmp(thistrans->TransName, typebuf))
|
||
found = 1;
|
||
typetocheck = workingXLOCAL;
|
||
}
|
||
TRANS(LocalEndTransports)();
|
||
|
||
if (!found) {
|
||
PRMSG(3,"LocalOpenCOTSServer: disabling %s\n",thistrans->TransName,0,0);
|
||
thistrans->flags |= TRANS_DISABLED;
|
||
return NULL;
|
||
}
|
||
|
||
return TRANS(LocalOpenServer)(XTRANS_OPEN_COTS_SERVER, protocol, host, port);
|
||
}
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalOpenCLTSClient)(Xtransport *thistrans, char *protocol,
|
||
char *host, char *port)
|
||
|
||
{
|
||
PRMSG(2,"LocalOpenCLTSClient(%s,%s,%s)\n",protocol,host,port);
|
||
|
||
return TRANS(LocalOpenClient)(XTRANS_OPEN_CLTS_CLIENT, protocol, host, port);
|
||
}
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalOpenCLTSServer)(Xtransport *thistrans, char *protocol,
|
||
char *host, char *port)
|
||
|
||
{
|
||
PRMSG(2,"LocalOpenCLTSServer(%s,%s,%s)\n",protocol,host,port);
|
||
|
||
return TRANS(LocalOpenServer)(XTRANS_OPEN_CLTS_SERVER, protocol, host, port);
|
||
}
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
|
||
#ifdef TRANS_REOPEN
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalReopenCOTSServer)(Xtransport *thistrans, int fd, char *port)
|
||
|
||
{
|
||
int index;
|
||
|
||
PRMSG(2,"LocalReopenCOTSServer(%d,%s)\n", fd, port, 0);
|
||
|
||
for(index=1;index<NUMTRANSPORTS;index++)
|
||
{
|
||
if( strcmp(thistrans->TransName,
|
||
LOCALtrans2devtab[index].transname) == 0 )
|
||
break;
|
||
}
|
||
|
||
if (index >= NUMTRANSPORTS)
|
||
{
|
||
return (NULL);
|
||
}
|
||
|
||
return TRANS(LocalReopenServer)(XTRANS_OPEN_COTS_SERVER,
|
||
index, fd, port);
|
||
}
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalReopenCLTSServer)(Xtransport *thistrans, int fd, char *port)
|
||
|
||
{
|
||
int index;
|
||
|
||
PRMSG(2,"LocalReopenCLTSServer(%d,%s)\n", fd, port, 0);
|
||
|
||
for(index=1;index<NUMTRANSPORTS;index++)
|
||
{
|
||
if( strcmp(thistrans->TransName,
|
||
LOCALtrans2devtab[index].transname) == 0 )
|
||
break;
|
||
}
|
||
|
||
if (index >= NUMTRANSPORTS)
|
||
{
|
||
return (NULL);
|
||
}
|
||
|
||
return TRANS(LocalReopenServer)(XTRANS_OPEN_CLTS_SERVER,
|
||
index, fd, port);
|
||
}
|
||
|
||
#endif /* TRANS_REOPEN */
|
||
|
||
|
||
|
||
static int
|
||
TRANS(LocalSetOption)(XtransConnInfo ciptr, int option, int arg)
|
||
|
||
{
|
||
PRMSG(2,"LocalSetOption(%d,%d,%d)\n",ciptr->fd,option,arg);
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
#ifdef TRANS_SERVER
|
||
|
||
static int
|
||
TRANS(LocalCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
|
||
|
||
{
|
||
PRMSG(2,"LocalCreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalResetListener)(XtransConnInfo ciptr)
|
||
|
||
{
|
||
LOCALtrans2dev *transptr;
|
||
|
||
PRMSG(2,"LocalResetListener(%x)\n",ciptr,0,0);
|
||
|
||
transptr=(LOCALtrans2dev *)ciptr->priv;
|
||
if (transptr->devreset != NULL) {
|
||
return transptr->devreset(ciptr);
|
||
}
|
||
return TRANS_RESET_NOOP;
|
||
}
|
||
|
||
|
||
static XtransConnInfo
|
||
TRANS(LocalAccept)(XtransConnInfo ciptr, int *status)
|
||
|
||
{
|
||
XtransConnInfo newciptr;
|
||
LOCALtrans2dev *transptr;
|
||
|
||
PRMSG(2,"LocalAccept(%x->%d)\n", ciptr, ciptr->fd,0);
|
||
|
||
transptr=(LOCALtrans2dev *)ciptr->priv;
|
||
|
||
if( (newciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo)))==NULL )
|
||
{
|
||
PRMSG(1,"LocalAccept: calloc(1,%d) failed\n",
|
||
sizeof(struct _XtransConnInfo),0,0 );
|
||
*status = TRANS_ACCEPT_BAD_MALLOC;
|
||
return NULL;
|
||
}
|
||
|
||
newciptr->fd=transptr->devaccept(ciptr,newciptr,status);
|
||
|
||
if( newciptr->fd < 0 )
|
||
{
|
||
xfree(newciptr);
|
||
return NULL;
|
||
}
|
||
|
||
newciptr->priv=(char *)transptr;
|
||
newciptr->index = ciptr->index;
|
||
|
||
*status = 0;
|
||
|
||
return newciptr;
|
||
}
|
||
|
||
#endif /* TRANS_SERVER */
|
||
|
||
|
||
#ifdef TRANS_CLIENT
|
||
|
||
static int
|
||
TRANS(LocalConnect)(XtransConnInfo ciptr, char *host, char *port)
|
||
|
||
{
|
||
PRMSG(2,"LocalConnect(%x->%d,%s)\n", ciptr, ciptr->fd, port);
|
||
|
||
return 0;
|
||
}
|
||
|
||
#endif /* TRANS_CLIENT */
|
||
|
||
|
||
static int
|
||
TRANS(LocalBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend )
|
||
|
||
{
|
||
PRMSG(2,"LocalBytesReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend);
|
||
|
||
#if defined(SCO325)
|
||
return ioctl(ciptr->fd, I_NREAD, (char *)pend);
|
||
#else
|
||
return ioctl(ciptr->fd, FIONREAD, (char *)pend);
|
||
#endif
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalRead)(XtransConnInfo ciptr, char *buf, int size)
|
||
|
||
{
|
||
PRMSG(2,"LocalRead(%d,%x,%d)\n", ciptr->fd, buf, size );
|
||
|
||
return read(ciptr->fd,buf,size);
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalWrite)(XtransConnInfo ciptr, char *buf, int size)
|
||
|
||
{
|
||
PRMSG(2,"LocalWrite(%d,%x,%d)\n", ciptr->fd, buf, size );
|
||
|
||
return write(ciptr->fd,buf,size);
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalReadv)(XtransConnInfo ciptr, struct iovec *buf, int size)
|
||
|
||
{
|
||
PRMSG(2,"LocalReadv(%d,%x,%d)\n", ciptr->fd, buf, size );
|
||
|
||
return READV(ciptr,buf,size);
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalWritev)(XtransConnInfo ciptr, struct iovec *buf, int size)
|
||
|
||
{
|
||
PRMSG(2,"LocalWritev(%d,%x,%d)\n", ciptr->fd, buf, size );
|
||
|
||
return WRITEV(ciptr,buf,size);
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalDisconnect)(XtransConnInfo ciptr)
|
||
|
||
{
|
||
PRMSG(2,"LocalDisconnect(%x->%d)\n", ciptr, ciptr->fd, 0);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalClose)(XtransConnInfo ciptr)
|
||
|
||
{
|
||
struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr;
|
||
int ret;
|
||
|
||
PRMSG(2,"LocalClose(%x->%d)\n", ciptr, ciptr->fd ,0);
|
||
|
||
ret=close(ciptr->fd);
|
||
|
||
if(ciptr->flags
|
||
&& sockname
|
||
&& sockname->sun_family == AF_UNIX
|
||
&& sockname->sun_path[0] )
|
||
{
|
||
if (!(ciptr->flags & TRANS_NOUNLINK))
|
||
unlink(sockname->sun_path);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
static int
|
||
TRANS(LocalCloseForCloning)(XtransConnInfo ciptr)
|
||
|
||
{
|
||
int ret;
|
||
|
||
PRMSG(2,"LocalCloseForCloning(%x->%d)\n", ciptr, ciptr->fd ,0);
|
||
|
||
/* Don't unlink path */
|
||
|
||
ret=close(ciptr->fd);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
/*
|
||
* MakeAllCOTSServerListeners() will go through the entire Xtransports[]
|
||
* array defined in Xtrans.c and try to OpenCOTSServer() for each entry.
|
||
* We will add duplicate entries to that table so that the OpenCOTSServer()
|
||
* function will get called once for each type of local transport.
|
||
*
|
||
* The TransName is in lowercase, so it will never match during a normal
|
||
* call to SelectTransport() in Xtrans.c.
|
||
*/
|
||
|
||
#ifdef TRANS_SERVER
|
||
static char * local_aliases[] = {
|
||
# ifdef LOCAL_TRANS_PTS
|
||
"pts",
|
||
# endif
|
||
"named",
|
||
# ifdef sun
|
||
"pipe", /* compatibility with Solaris Xlib */
|
||
# endif
|
||
# ifdef LOCAL_TRANS_SCO
|
||
"sco",
|
||
# endif
|
||
NULL };
|
||
#endif
|
||
|
||
Xtransport TRANS(LocalFuncs) = {
|
||
/* Local Interface */
|
||
"local",
|
||
TRANS_ALIAS | TRANS_LOCAL,
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCOTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
local_aliases,
|
||
TRANS(LocalOpenCOTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCLTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalOpenCLTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(LocalReopenCOTSServer),
|
||
TRANS(LocalReopenCLTSServer),
|
||
#endif
|
||
TRANS(LocalSetOption),
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalCreateListener),
|
||
TRANS(LocalResetListener),
|
||
TRANS(LocalAccept),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalConnect),
|
||
#endif /* TRANS_CLIENT */
|
||
TRANS(LocalBytesReadable),
|
||
TRANS(LocalRead),
|
||
TRANS(LocalWrite),
|
||
TRANS(LocalReadv),
|
||
TRANS(LocalWritev),
|
||
TRANS(LocalDisconnect),
|
||
TRANS(LocalClose),
|
||
TRANS(LocalCloseForCloning),
|
||
};
|
||
|
||
#ifdef LOCAL_TRANS_PTS
|
||
|
||
Xtransport TRANS(PTSFuncs) = {
|
||
/* Local Interface */
|
||
"pts",
|
||
TRANS_LOCAL,
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCOTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
NULL,
|
||
TRANS(LocalOpenCOTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCLTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalOpenCLTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(LocalReopenCOTSServer),
|
||
TRANS(LocalReopenCLTSServer),
|
||
#endif
|
||
TRANS(LocalSetOption),
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalCreateListener),
|
||
TRANS(LocalResetListener),
|
||
TRANS(LocalAccept),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalConnect),
|
||
#endif /* TRANS_CLIENT */
|
||
TRANS(LocalBytesReadable),
|
||
TRANS(LocalRead),
|
||
TRANS(LocalWrite),
|
||
TRANS(LocalReadv),
|
||
TRANS(LocalWritev),
|
||
TRANS(LocalDisconnect),
|
||
TRANS(LocalClose),
|
||
TRANS(LocalCloseForCloning),
|
||
};
|
||
|
||
#endif /* LOCAL_TRANS_PTS */
|
||
|
||
#ifdef LOCAL_TRANS_NAMED
|
||
|
||
Xtransport TRANS(NAMEDFuncs) = {
|
||
/* Local Interface */
|
||
"named",
|
||
TRANS_LOCAL,
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCOTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
NULL,
|
||
TRANS(LocalOpenCOTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCLTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalOpenCLTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(LocalReopenCOTSServer),
|
||
TRANS(LocalReopenCLTSServer),
|
||
#endif
|
||
TRANS(LocalSetOption),
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalCreateListener),
|
||
TRANS(LocalResetListener),
|
||
TRANS(LocalAccept),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalConnect),
|
||
#endif /* TRANS_CLIENT */
|
||
TRANS(LocalBytesReadable),
|
||
TRANS(LocalRead),
|
||
TRANS(LocalWrite),
|
||
TRANS(LocalReadv),
|
||
TRANS(LocalWritev),
|
||
TRANS(LocalDisconnect),
|
||
TRANS(LocalClose),
|
||
TRANS(LocalCloseForCloning),
|
||
};
|
||
|
||
#ifdef sun
|
||
Xtransport TRANS(PIPEFuncs) = {
|
||
/* Local Interface */
|
||
"pipe",
|
||
TRANS_ALIAS | TRANS_LOCAL,
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCOTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
NULL,
|
||
TRANS(LocalOpenCOTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCLTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalOpenCLTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(LocalReopenCOTSServer),
|
||
TRANS(LocalReopenCLTSServer),
|
||
#endif
|
||
TRANS(LocalSetOption),
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalCreateListener),
|
||
TRANS(LocalResetListener),
|
||
TRANS(LocalAccept),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalConnect),
|
||
#endif /* TRANS_CLIENT */
|
||
TRANS(LocalBytesReadable),
|
||
TRANS(LocalRead),
|
||
TRANS(LocalWrite),
|
||
TRANS(LocalReadv),
|
||
TRANS(LocalWritev),
|
||
TRANS(LocalDisconnect),
|
||
TRANS(LocalClose),
|
||
TRANS(LocalCloseForCloning),
|
||
};
|
||
#endif /* sun */
|
||
#endif /* LOCAL_TRANS_NAMED */
|
||
|
||
|
||
#ifdef LOCAL_TRANS_SCO
|
||
Xtransport TRANS(SCOFuncs) = {
|
||
/* Local Interface */
|
||
"sco",
|
||
TRANS_LOCAL,
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCOTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
NULL,
|
||
TRANS(LocalOpenCOTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalOpenCLTSClient),
|
||
#endif /* TRANS_CLIENT */
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalOpenCLTSServer),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_REOPEN
|
||
TRANS(LocalReopenCOTSServer),
|
||
TRANS(LocalReopenCLTSServer),
|
||
#endif
|
||
TRANS(LocalSetOption),
|
||
#ifdef TRANS_SERVER
|
||
TRANS(LocalCreateListener),
|
||
TRANS(LocalResetListener),
|
||
TRANS(LocalAccept),
|
||
#endif /* TRANS_SERVER */
|
||
#ifdef TRANS_CLIENT
|
||
TRANS(LocalConnect),
|
||
#endif /* TRANS_CLIENT */
|
||
TRANS(LocalBytesReadable),
|
||
TRANS(LocalRead),
|
||
TRANS(LocalWrite),
|
||
TRANS(LocalReadv),
|
||
TRANS(LocalWritev),
|
||
TRANS(LocalDisconnect),
|
||
TRANS(LocalClose),
|
||
TRANS(LocalCloseForCloning),
|
||
};
|
||
#endif /* LOCAL_TRANS_SCO */
|