Re: Finding my $DISPLAY programatically.
Re: Finding my $DISPLAY programatically.
- Subject: Re: Finding my $DISPLAY programatically.
- From: Robert Tillyard <email@hidden>
- Date: Sat, 3 May 2008 23:43:11 +0100
I think I found a solution to this using suggestions from those who
replied (see below).
I know some of you may find it annoying that I don't want to use ssh
for this but I have several hundred SCO UNIX systems throughout the UK
installed over the last sixteen years, each ranging from 3 to 100
users and only the recent ones are accessible by broadband.
The Macs are used as work stations, they're imaged, the IP address is
set-up then they're installed on site. If one breaks (two or three die
and need re-imaging each month) we image another and send it out as a
user swap item. We need static IP addresses as the IP address tells
the server which room and site you're in so that printers can be
assigned by location and private data can be hidden if the screen is
defined as one that the public can see rather than a back-office screen.
The Macs don't know the users or their passwords on the server, when
fired up for the first time they download the menu from the server
which defines the remote commands to run via rexec for various parts
of the system and all that it required is a user name and password.
I've cobbled together some code below that when compiled will return
the DISPLAY as required from a remote host.
This code works for my situation and hasn't had much testing, and I
need to tidy it up. It doesn't work for the root user and probably
won't work if you have multiple network cards or multiple IP
addresses. It also only works on IPv4 but then I don't know if X11
will take an IPv6 IP address in DISPLAY.
Thanks for your help everybody. Regards, Rob.
Compile using: gcc xdpyspec.m -framework CoreFoundation -framework
Foundation -o xdpyspec
// xdpyspec.m
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <Foundation/Foundation.h>
#define L_IPAddress (16) // IPv4
typedef struct kinfo_proc kinfo_proc;
static void usage (void);
static void processArgs (int argc, char **argv);
static char *getIPAddress (void);
static int strcntchr (const char *, char);
static int doProcessing (int argc, char **argv);
static pid_t findXquartz (void);
static bool getScreenForPID (pid_t pid, int *screen);
static char *programName;
int main (int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int r;
r = doProcessing (argc, argv);
[pool release];
return (r);
}
static int doProcessing (int argc, char **argv)
{
char *p;
int screen = 0;
pid_t pid;
processArgs (argc, argv);
if ((pid = findXquartz ()) == 0)
{
fprintf (stderr, "Failed to locate Xquartz process\n");
return (1);
}
if ((p = getIPAddress ()) == (char *) 0L)
return (1);
getScreenForPID (pid, &screen);
printf ("%s:%d.0\n", p, screen);
return (0);
}
static char *getIPAddress ()
{
static char buffer [L_IPAddress + 1];
NSArray *a;
int i;
const char *p;
// Add our own IP Address.
a = [[NSHost currentHost] addresses];
for (i = 0; i < [a count]; i ++)
{
if ((p = [[a objectAtIndex:i] cString]) == (const char *) 0L)
continue;
if (strcmp (p, "127.0.0.1") == 0)
continue;
if (strchr (p, ':'))
continue;
if (strcntchr (p, '.') == 3)
{
strcpy (buffer, p);
return (buffer);
}
}
return ((char *) 0L);
}
static pid_t findXquartz ()
{
pid_t pid = 0;
kinfo_proc *procs = (kinfo_proc *) 0L;
size_t count = 0;
size_t i;
uid_t uid;
uid = getuid ();
if (GetBSDProcessList (&procs, &count) != 0)
return (0);
for (i = 0; i < count; i ++)
{
// Compare the process name and don't get confused if another
user
// is running the same process (check uid).
if (strcmp (procs [i].kp_proc.p_comm, "Xquartz") == 0 &&
procs [i].kp_eproc.e_pcred.p_ruid == uid)
{
pid = procs [i].kp_proc.p_pid;
break;
}
}
free (procs);
return (pid);
}
// GetBSDProcessList() (c)Apple from Apple Example Code
// See http://developer.apple.com/qa/qa2001/qa1123.html
int GetBSDProcessList (kinfo_proc **procList, size_t *procCount)
{
int err;
kinfo_proc *result;
bool done;
static const int name [] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
size_t length;
*procCount = 0;
result = NULL;
done = false;
do {
// Call sysctl with a NULL buffer.
length = 0;
if ((err = sysctl ((int *) name,
(sizeof (name) / sizeof (*name)) - 1,
NULL, &length,
NULL, 0)) == -1)
err = errno;
// Allocate an appropriately sized buffer based on the results
// from the previous call.
if (err == 0)
if ((result = malloc (length)) == NULL)
err = ENOMEM;
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
if (err == 0)
{
if ((err = sysctl ((int *) name,
(sizeof (name) / sizeof (*name)) - 1,
result,
&length,
NULL, 0)) == -1)
err = errno;
if (err == 0)
done = true;
else if (err == ENOMEM)
{
free (result);
result = NULL;
err = 0;
}
}
} while (err == 0 && ! done);
// Clean up and establish post conditions.
if (err != 0 && result != NULL)
{
free (result);
result = NULL;
}
*procList = result;
if (err == 0)
*procCount = length / sizeof (kinfo_proc);
return (err);
}
static bool getScreenForPID (pid_t pid, int *screen)
{
char buffer [128];
char field [128];
FILE *fp;
pid_t xpid;
char *p;
int scrn;
bool r = 0;
if ((fp = popen ("lsof", "r")) == (FILE *) 0L)
return (0);
while (fgets (buffer, 127, fp))
{
if (sscanf (buffer, "%*s %d\n", &xpid) != 1 || xpid != pid)
continue;
if (sscanf (buffer, "%*s %*s %*s %*s %s\n", field) != 1)
continue;
if (strcmp (field, "IPv4") != 0)
continue;
if ((p = strrchr (buffer, ':')) == (char *) 0L)
continue;
p ++;
scrn = atoi (p);
if (scrn >= 6000)
{
*screen = scrn - 6000;
r = 1;
}
}
fclose (fp);
return (r);
}
static int strcntchr (const char *str, char c)
{
int count = 0;
const char *p = str;
while (*p)
if (*p ++ == c)
count ++;
return (count);
}
static void processArgs (int argc, char **argv)
{
int i;
char *p;
// Sort out the program name.
programName = argv [0];
if ((p = strrchr (programName, '/')))
programName = p + 1;
#ifdef __Never
for (i = 1 ; i < argc ; i ++)
if (argv [i][0] == '-')
switch (argv [i][1])
{
case
}
#endif
}
static void usage ()
{
fprintf (stderr, "usage: %s \n", programName);
exit (1);
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
X11-users mailing list (email@hidden)
This email sent to email@hidden