824N/A/*
824N/A csstartNX.c
824N/A
824N/A * (c) Copyright 1992-1994 Adobe Systems Incorporated.
824N/A * All rights reserved.
824N/A *
824N/A * Permission to use, copy, modify, distribute, and sublicense this software
824N/A * and its documentation for any purpose and without fee is hereby granted,
824N/A * provided that the above copyright notices appear in all copies and that
824N/A * both those copyright notices and this permission notice appear in
824N/A * supporting documentation and that the name of Adobe Systems Incorporated
824N/A * not be used in advertising or publicity pertaining to distribution of the
824N/A * software without specific, written prior permission. No trademark license
824N/A * to use the Adobe trademarks is hereby granted. If the Adobe trademark
824N/A * "Display PostScript"(tm) is used to describe this software, its
824N/A * functionality or for any other purpose, such use shall be limited to a
824N/A * statement that this software works in conjunction with the Display
824N/A * PostScript system. Proper trademark attribution to reflect Adobe's
824N/A * ownership of the trademark shall be given whenever any such reference to
824N/A * the Display PostScript system is made.
824N/A *
824N/A * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
824N/A * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
824N/A * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
824N/A * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
824N/A * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
824N/A * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
824N/A * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
824N/A * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
824N/A * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
824N/A * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
824N/A *
824N/A * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
824N/A * Incorporated which may be registered in certain jurisdictions
824N/A *
824N/A * Author: Adobe Systems Incorporated
824N/A */
824N/A/* $XFree86: xc/lib/dps/csstartNX.c,v 1.6 2001/10/28 03:32:43 tsi Exp $ */
824N/A
824N/A#include <sys/param.h>
824N/A#include <X11/X.h>
824N/A#include <X11/Xlibint.h>
824N/A#include <sys/wait.h>
824N/A#include <DPS/dpsNXargs.h>
824N/A#include <sys/socket.h>
824N/A#include <errno.h>
824N/A#include <X11/Xos.h>
824N/A
824N/A#include "DPSCAPproto.h"
824N/A#include "Xlibnet.h" /* New for R5, delete for R4 */
824N/A#include "dpsassert.h"
824N/A#include "csfindNX.h"
824N/A#include "csstartNX.h"
824N/A
824N/A/* ---Defines--- */
824N/A
824N/A#include <stddef.h>
824N/A
824N/A#define DOZETIME 1 /* time to wait for agent to start up (sec) */
824N/A
824N/A#define BASE_TCP_PORT CSDPSPORT
824N/A
824N/A#ifndef CSDPSMAXPORT
824N/A#define CSDPSMAXPORT 16
824N/A#endif
824N/A
824N/A#ifndef SO_REUSEADDR
824N/A#define SO_REUSEADDR 1
824N/A#endif
824N/A
824N/A/* ---Globals--- */
824N/A
824N/Apid_t gSecretAgentPID = 0; /* PID of launched agent *Shh!* Not public! */
824N/A
824N/A/* ---Private Functions--- */
824N/A
824N/Astatic int
824N/ATryTCP(void)
824N/A{
824N/A struct sockaddr_in insock;
824N/A int request;
824N/A unsigned short port, startPort = 0;
824N/A struct servent *serventInfo;
824N/A int okay;
824N/A
824N/A#ifndef ultrix
824N/A /* Ultrix has a nasty bug in getservbyname(). If the name passed
824N/A to it doesn't exist in the services list it will seg. fault...
824N/A * sigh * */
824N/A if ((serventInfo = getservbyname(DPS_NX_SERV_NAME,
824N/A (char *) 0)) != 0)
824N/A if (strcmp("tcp", serventInfo->s_proto) == 0) {
824N/A startPort = ntohs(serventInfo->s_port);
824N/A }
824N/A /* So, for Ultrix we just default to the default default port :-) */
824N/A#endif /* ultrix */
824N/A if (startPort == 0) startPort = BASE_TCP_PORT;
824N/A if ((request = socket (AF_INET, SOCK_STREAM, 0)) < 0)
824N/A {
824N/A DPSWarnProc(NULL, "Creating TCP socket while recommending port\n");
824N/A return -1;
824N/A }
824N/A#ifdef SO_REUSEADDR
824N/A /* Necesary to restart the server without a reboot */
824N/A {
824N/A int one = 1;
824N/A setsockopt(request, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int));
824N/A }
824N/A /* What the hell is all this? I'll tell you. We don't know
824N/A a prioi what port is free, so we try to bind to each
824N/A in sequence and return the one that works. */
824N/A#if !defined(AIXV3)
824N/A {
824N/A struct linger lingere;
824N/A
824N/A lingere.l_onoff = 0; /* off */
824N/A lingere.l_linger = 0; /* don't */
824N/A if(setsockopt(request, SOL_SOCKET, SO_LINGER, (char *)&lingere,
824N/A sizeof(struct linger)) != 0)
824N/A DPSWarnProc(NULL,
824N/A "Couldn't set TCP SO_DONTLINGER while recommending port.");
824N/A }
824N/A#endif /* AIXV3 */
824N/A#endif /* SO_REUSEADDR */
824N/A bzero((char *)&insock, sizeof (insock));
824N/A insock.sin_family = AF_INET;
824N/A insock.sin_addr.s_addr = htonl(INADDR_ANY);
824N/A okay = 0;
824N/A
824N/A for (port = startPort; (int) port < (int) startPort + CSDPSMAXPORT; port++)
824N/A {
824N/A int result;
824N/A insock.sin_port = htons(port);
824N/A
824N/A errno = 0;
824N/A result = bind(request, (struct sockaddr *) &insock, sizeof (insock));
824N/A if (result < 0)
824N/A {
824N/A if (errno != EADDRINUSE)
824N/A {
824N/A DPSWarnProc(NULL, "Binding TCP socket while recommending port.\n");
824N/A close(request);
824N/A return -1;
824N/A }
824N/A continue;
824N/A }
824N/A else
824N/A {
824N/A /* We have a good port number */
824N/A okay = 1;
824N/A break;
824N/A }
824N/A }
824N/A close(request);
824N/A return (okay) ? port : -1;
824N/A}
824N/A
824N/A/* ---Functions--- */
824N/A
824N/Aint
824N/AXDPSNXRecommendPort(int transport)
824N/A{
824N/A int ret;
824N/A
824N/A switch (transport)
824N/A {
824N/A case XDPSNX_TRANS_UNIX:
824N/A /* If the TCP socket exists, we just assume the UNIX one
824N/A is there too. FALL THRU! */
824N/A case XDPSNX_TRANS_TCP: /* TCP */
824N/A ret = TryTCP();
824N/A break;
824N/A default: ret = -1;
824N/A }
824N/A return(ret);
824N/A}
824N/A
824N/Aint
824N/AStartXDPSNX(char **additionalArgs)
824N/A{
824N/A char **args, **cpp;
824N/A pid_t childPid;
824N/A int argc = 1; /* 1, args[0]:=path, args[1]:=null */
824N/A int i = 0;
824N/A int status = Success; /* assume we'll succeed */
824N/A char *execObj, **execArgs;
824N/A
824N/A (void) XDPSGetNXArg(XDPSNX_EXEC_FILE, (void **) &execObj);
824N/A if (execObj == 0) return (!Success);
824N/A
824N/A /* Create the argv list for the execl() call */
824N/A (void) XDPSGetNXArg(XDPSNX_EXEC_ARGS, (void **) &execArgs);
824N/A if (execArgs != 0)
824N/A for(cpp = execArgs; *cpp != 0; cpp++, argc++); /* count args. */
824N/A if (additionalArgs != 0) /* add on the add-on args. */
824N/A for(cpp = additionalArgs; *cpp != 0; cpp++, argc++);
824N/A
824N/A args = (char **) Xmalloc(sizeof(char *) * (argc+1));
824N/A if (args == 0)
824N/A return(!Success);
824N/A args[argc] = 0; /* cap end of args */
824N/A args[i++] = execObj;
824N/A if (additionalArgs != 0)
824N/A for(cpp = additionalArgs; *cpp != 0; cpp++, i++) args[i] = *cpp;
824N/A if (execArgs != 0)
824N/A for(cpp = execArgs; *cpp != 0; cpp++, i++) args[i] = *cpp;
824N/A
824N/A /* now try to start up the agent... */
824N/A if ((childPid = fork()) != -1) {
824N/A if (childPid == 0) { /* Child process */
824N/A#ifndef __UNIXOS2__
824N/A if (setsid() < 0)
824N/A DPSWarnProc(NULL, "Agent unable to create session. Continuing...\n");
824N/A#endif
824N/A
824N/A /* Try to start the agent */
824N/A if (execvp(args[0], args) < 0) { /* Error!! */
824N/A exit(1); /* This is OKAY, we're the child here */
824N/A }
824N/A /* SHOULD NEVER REACH HERE */
824N/A } else { /* Parent (NX Client) */
824N/A (void) sleep(DOZETIME);
824N/A /* if decmips, pray that we hesitate long enough for the child... */
824N/A /* Check on child (NX Agent) */
824N/A if (waitpid(childPid, NULL, WNOHANG) != 0) {
824N/A /* Server terminated or stopped; don't care, result is same... */
824N/A status = !Success;
824N/A } else { /* we think the agent started okay */
824N/A gSecretAgentPID = childPid; /* set secret global */
824N/A }
824N/A }
824N/A } else { /* Error in fork */
824N/A status = !Success;
824N/A }
824N/A if (args != 0) (void) XFree(args);
824N/A return(status);
824N/A}