Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!think.com!mintaka!bloom-beacon!eru!hagbard!sunic!kth.se!hemuli.tik.vtt.fi!tml From: tml@tik.vtt.fi (Tor Lillqvist) Newsgroups: comp.sys.hp Subject: Re: X on 9000/318's Message-ID: Date: 2 Nov 90 19:27:13 GMT References: Sender: news@hemuli.tik.vtt.fi Distribution: comp Organization: Technical Research Centre of Finland, Laboratory for Information Processing (VTT/TIK) Lines: 328 In-reply-to: mahesh@shark.cs.fau.edu's message of 2 Nov 90 04:47:50 GMT In article mahesh@shark.cs.fau.edu (Mahesh Neelakanta) writes: Greetings, We have about 7 hp 9000/318 which used to be faculty workstations before we got some 345's. The 318's have 4 Megs are are now diskless student machines. The problem: X11 barely runs on these things. It is *real* slow and unresponsive. My questions is: Is there a way of running the X11 Server on one of our more powerful hp's and run a small program on the diskless which just draws to the screen. No you cannot run the X server remotely. But something like this is possible. Basically you generate a really minimal kernel (tune down nproc, ntext, npty, nbuf etc), and put in /etc/inittab: is:2:initdefault: st::sysinit:stty 9600 clocal icanon echo opost onlcr ienqak ixon icrnl ignpar < /dev/systty bc::bootwait:/etc/brc 1>/dev/syscon 2>&1 #bootrun command cr::bootwait:/bin/cat /etc/copyright >/dev/syscon rc::wait:/etc/rc.x-terminal /dev/syscon 2>&1 #run com co:023456:respawn:/usr/bin/X11/X -query host.running.xdm >/dev/console 2>&1 and /etc/rc.x-terminal is: #!/bin/sh set -- `getcontext` && cnodename=$1 hostname ... ifconfig lan0 `hostname` up /etc/xlockserver Then you run some X Display Manager program on another host, and it manages the 318 like an X Terminal. Unfortunately xdm as supplied by MIT doesn't work too well on HP-UX (some confusion about signal semantics etc). But if you have VUE, I think vuesession is xdm in disguise. I did try this once when we still had 318s, but it didn't work too well (we didn't have VUE then), and I didn't have time to look into it more deeply. And the people with 318s were not too dissatisfied after all... If you cannot get the xdm/vuesession approach working, you could keep getty and let people log in normally, but have /etc/profile start the X server and remsh a hpterm/xterm on a remote host. Etc. The xlockserver mentioned above is a really small program: xxxxxxxxxxxxxxxx cut here xxxxxxxxxxxxxxxx /* * S E R V . U D P * * This is an example program that demonstrates the use of datagram sockets as * an IPC mechanism. This contains the server, and is intended to operate in * conjunction with the client program found in client.udp. Together, these * two programs demonstrate many of the features of sockets, as well as good * conventions for using these features. * * This program provides a service called "xlock". It starts the xlock program. * In order for it to function, an entry for it needs to exist in the * /etc/services file. The port address for this service can be any port * number that is likely to be unused, such as 22375, for example. The host * on which the client will be running must also have the same entry (same * port number) in its /etc/services file. * */ #include #include #include #include #include #include int s; /* socket descriptor */ #define BUFFERSIZE 17 /* maximum size of packets to be received */ int cc; /* contains the number of bytes read */ char buffer[BUFFERSIZE]; /* buffer for packets to be read into */ struct servent *sp; /* pointer to service information */ struct sockaddr_in myaddr_in; /* for local socket address */ struct sockaddr_in clientaddr_in; /* for client's socket address */ /* * M A I N * * This routine starts the server. It forks, leaving the child to do all the * work, so it does not have to be run in the background. It sets up the * socket, and for each incoming request, it starts xlock. The request * contains the name of the user. * */ main(argc, argv) int argc; char *argv[]; { int addrlen; struct passwd *pwd; /* clear out address structures */ memset((char *) &myaddr_in, 0, sizeof(struct sockaddr_in)); memset((char *) &clientaddr_in, 0, sizeof(struct sockaddr_in)); /* Set up address structure for the socket. */ myaddr_in.sin_family = AF_INET; /* * The server should receive on the wildcard address, rather than its * own internet address. This is generally good practice for * servers, because on systems which are connected to more than one * network at once will be able to have one server listening on all * networks at once. Even when the host is connected to only one * network, this is good practice, because it makes the server * program more portable. */ myaddr_in.sin_addr.s_addr = INADDR_ANY; /* * Find the information for the "xlock" server in order to get the * needed port number. */ sp = getservbyname("xlock", "udp"); if (sp == NULL) { fprintf(stderr, "%s: xlock not found in /etc/services\n", argv[0]); exit(1); } myaddr_in.sin_port = sp->s_port; /* Create the socket. */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) { perror(argv[0]); fprintf(stderr, "%s: unable to create socket\n", argv[0]); exit(1); } /* Bind the server's address to the socket. */ if (bind(s, &myaddr_in, sizeof(struct sockaddr_in)) == -1) { perror(argv[0]); fprintf(stderr, "%s: unable to bind address\n", argv[0]); exit(1); } /* * Now, all the initialization of the server is complete, and any * user errors will have already been detected. Now we can fork the * daemon and return to the user. We need to do a setpgrp so that * the daemon will no longer be associated with the user's control * terminal. This is done before the fork, so that the child will * not be a process group leader. Otherwise, if the child were to * open a terminal, it would become associated with that terminal as * its control terminal. It is always best for the parent to do the * setpgrp. */ setpgrp(); switch (fork()) { case -1: /* Unable to fork, for some reason. */ perror(argv[0]); fprintf(stderr, "%s: unable to fork daemon\n", argv[0]); exit(1); case 0: /* The child process (daemon) comes here. */ for (;;) { /* * Note that addrlen is passed as a pointer so that * the recvfrom call can return the size of the * returned address. */ addrlen = sizeof(struct sockaddr_in); /* * This call will block until a new request arrives. * Then, it will return the address of the client, * and a buffer containing its request. BUFFERSIZE - * 1 bytes are read so that room is left at the end * of the buffer for a null character. */ cc = recvfrom(s, buffer, BUFFERSIZE - 1, 0, &clientaddr_in, &addrlen); if (cc == -1) { perror(argv[0]); exit(1); } buffer[cc] = '\0'; if ((pwd = getpwnam(buffer)) == NULL) { fprintf(stderr, "%s: unknown user %s\n"); exit(1); } /* Fork and exec xlock */ switch (fork()) { case -1: perror(argv[0]); fprintf(stderr, "%s: unable to fork xlock\n", argv[0]); break; case 0: setgid(pwd->pw_gid); setuid(pwd->pw_uid); execl("/usr/bin/X11/xlock", "xlock", (char *) NULL); default: wait((int *) NULL); } } default: /* Parent process comes here. */ exit(0); } } xxxxxxxxxxxxxxxx cut here xxxxxxxxxxxxxxxx and you run the corresponding client on the remote host: xxxxxxxxxxxxxxxx cut here xxxxxxxxxxxxxxxx /* * C L I E N T . U D P * * This is an example program that demonstrates the use of datagram sockets as * an IPC mechanism. This contains the client, and is intended to operate in * conjunction with the server program found in serv.udp. Together, these * two programs demonstrate many of the features of sockets, as well as good * conventions for using these features. * * This program requests a service called "xlock". In order for it to function, * an entry for it needs to exist in the /etc/services file. The port * address for this service can be any port number that is likely to be * unused, such as 22375, for example. The host on which the server will be * running must also have the same entry (same port number) in its * /etc/services file. * * The "xlock" service is starts the xlock program on an "X terminal mode" * workstation, i.e. a workstation that has only the X server and the xlock * server running, so that the user has no way to start xlock (normally * started from the window manager). * */ #include #include #include #include #include #include extern int errno; int s; /* socket descriptor */ struct hostent *hp; /* pointer to host info for nameserver host */ struct servent *sp; /* pointer to service information */ struct sockaddr_in myaddr_in; /* for local socket address */ struct sockaddr_in servaddr_in; /* for server socket address */ #define RETRIES 5 /* number of times to retry before givin up */ /* * M A I N * * This routine is the client which requests service from the remote "xlock * server". */ main(argc, argv) int argc; char *argv[]; { int i; int retry = RETRIES; /* holds the retry count */ char *display, *colon, *logname; char *inet_ntoa(); /* clear out address structures */ memset((char *) &myaddr_in, 0, sizeof(struct sockaddr_in)); memset((char *) &servaddr_in, 0, sizeof(struct sockaddr_in)); /* Set up the server address. */ servaddr_in.sin_family = AF_INET; /* * Get the host information for the server's hostname that the user * passed in. */ if ((display = getenv("DISPLAY")) == NULL) { fprintf(stderr, "No $DISPLAY.\n"); exit(1); } colon = strchr(display, ':'); if (colon == NULL) { fprintf(stderr, "Malformed $DISPLAY\n"); exit(1); } *colon = 0; hp = gethostbyname(display); if (hp == NULL) { fprintf(stderr, "%s: unknown host %s\n", argv[0], display); exit(1); } logname = getenv("LOGNAME"); servaddr_in.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; /* * Find the information for the "xlock" server in order to get the * needed port number. */ sp = getservbyname("xlock", "udp"); if (sp == NULL) { fprintf(stderr, "%s: xlock not found in /etc/services\n", argv[0]); exit(1); } servaddr_in.sin_port = sp->s_port; /* Create the socket. */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) { perror(argv[0]); fprintf(stderr, "%s: unable to create socket\n", argv[0]); exit(1); } /* Send the request. */ if (sendto(s, logname, strlen(logname), 0, &servaddr_in, sizeof(struct sockaddr_in)) == -1) { perror(argv[0]); fprintf(stderr, "%s: unable to send request\n", argv[0]); exit(1); } exit(0); } xxxxxxxxxxxxxxxx cut here xxxxxxxxxxxxxxxx -- Tor Lillqvist, working, but not speaking, for the Technical Research Centre of Finland