Can't display Java gui

  • Thread starter Conrad Eaglehill
  • Start date
C

Conrad Eaglehill

Hi.

I'm using sendmail 8.12.9 for a project on RedHat Fedora Core 2 on my
personal computer with a perfectly functioning X window server. Part
of this project requires me to modify sendmail to open a Java gui
application. When I attempted this originally, I got the following
error: "No X11 DISPLAY variable was set, but this program performed an
operation which requires it." Figuring that sendmail for whatever
reason unset it, I called the C function setenv() in sendmail to set
it and got the following error: "Exception in thread "main"
java.lang.InternalError: Can't connect to X11 window server using
'localhost:0.0' as the value of the DISPLAY variable." Using the
command-line imperative "-Djava.awt.headless=true" for the Java
program gives the following message: "Exception in thread "main"
java.awt.HeadlessException."

Looking into the problem, I found that when running as root, lots of
people have had the same problem, and their solution was "don't run as
root." Sendmail needs root permissions for some things, so this isn't
an option for me. I wonder if anyone know how to run a Java
application that needs the X-Window server as root, (or perhaps would
allow me to run a Java gui from sendmail as another user temporarily).

Thanks in advance,

Conrad Eaglehill
 
T

Thomas Weidenfeller

Conrad said:
Looking into the problem, I found that when running as root, lots of
people have had the same problem, and their solution was "don't run as
root." Sendmail needs root permissions for some things, so this isn't
an option for me. I wonder if anyone know how to run a Java
application that needs the X-Window server as root, (or perhaps would
allow me to run a Java gui from sendmail as another user temporarily).

I can't really see why anyone would like to start a GUI from a
background daemon like sendmail (especially, because there is no
guarantee that anyone is looking at the display), but well ...

To change your effective user user id, see:

man su
man sudo

But if you really need to alert someone from sendmail (why?), consider
using something like wall or syslog, or sending a pager/SMS message.

/Thomas
 
J

John C. Bollinger

Conrad said:
I'm using sendmail 8.12.9 for a project on RedHat Fedora Core 2 on my
personal computer with a perfectly functioning X window server. Part
of this project requires me to modify sendmail to open a Java gui
application. When I attempted this originally, I got the following
error: "No X11 DISPLAY variable was set, but this program performed an
operation which requires it." Figuring that sendmail for whatever
reason unset it, I called the C function setenv() in sendmail to set
it and got the following error: "Exception in thread "main"
java.lang.InternalError: Can't connect to X11 window server using
'localhost:0.0' as the value of the DISPLAY variable." Using the
command-line imperative "-Djava.awt.headless=true" for the Java
program gives the following message: "Exception in thread "main"
java.awt.HeadlessException."

Looking into the problem, I found that when running as root, lots of
people have had the same problem, and their solution was "don't run as
root." Sendmail needs root permissions for some things, so this isn't
an option for me. I wonder if anyone know how to run a Java
application that needs the X-Window server as root, (or perhaps would
allow me to run a Java gui from sendmail as another user temporarily).

Are you fork()ing a new process in which to launch the GUI? You ought
to be able to have that process change its euid and egid to
non-privileged ones, prior to exec()ing the JVM. Also, some of the
various exec calls allow you to specify the environment for the new
executable; this avoids unnecessarily propagating environment variables,
as well as giving you an easy hook for inserting new variables required
by the exec()ed program.

Or are you running it via the system() call? That's basically a wrapper
around the exec()-based technique; you could write your own replacement
that does what you want. Alternatively, if you're spawning the Java
program that way then you may want to look into using su -c.


John Bollinger
(e-mail address removed)
 
C

Conrad Eaglehill

John C. Bollinger said:
Are you fork()ing a new process in which to launch the GUI?

Sort of. I'm using a system() call.
You ought
to be able to have that process change its euid and egid to
non-privileged ones, prior to exec()ing the JVM.

I tried that, but the message remains the same. Interestingly, when I
call setuid() or seteuid() in my dummy program, I get the same sets of
errors, though without these calls, the Java app comes up just fine.
Also, some of the
various exec calls allow you to specify the environment for the new
executable; this avoids unnecessarily propagating environment variables,
as well as giving you an easy hook for inserting new variables required
by the exec()ed program.

Or are you running it via the system() call? That's basically a wrapper
around the exec()-based technique; you could write your own replacement
that does what you want.

I am actually using a system() call, and I thought about exec()ing,
but system() returns a value, whereas exec() calls never return. I use
the return value of the Java app to make decisions.
Alternatively, if you're spawning the Java
program that way then you may want to look into using su -c.

This is interesting. In my dummy program as ceaglehill (my account)...
"su -c ./dummy ceaglehill" => works when I enter a password
"su -c ./dummy root" => works when I enter a password

But as root...
"su -c ./dummy root" => works perfectly without password
"su -c ./dummy ceaglehill" => fails, giving me the same errors as
above

Of course, it is the last than I need. :-( Definitely good ideas,
though. I hadn't thought about "su -c" or the setuid() calls until you
brought them up. Any other tricks up your sleeve? :)
John Bollinger
(e-mail address removed)

Conrad Eaglehill
 
C

Conrad Eaglehill

Thomas Weidenfeller said:
I can't really see why anyone would like to start a GUI from a
background daemon like sendmail (especially, because there is no
guarantee that anyone is looking at the display), but well ...

To change your effective user user id, see:

man su
man sudo

"su -c progname username" works, sort of. When I'm root, and I try to
execute this program as another user, I get the same errors. When I am
a user and I try to execute the program as root, it works fine, except
I have to enter a password.
But if you really need to alert someone from sendmail (why?), consider
using something like wall or syslog, or sending a pager/SMS message.

Alas, I don't have a choice in the matter. As amm people, I do as I'm
told. The app isn't a logger, though. It displays visual info to the
user, and thus has to be a gui.

Thanks for the response, though!

Conrad Eaglehill
 
R

Robert Clark

Conrad said:
reason unset it, I called the C function setenv() in sendmail to set
it and got the following error: "Exception in thread "main"
java.lang.InternalError: Can't connect to X11 window server using
'localhost:0.0' as the value of the DISPLAY variable." Using the
[ snip ]

Looking into the problem, I found that when running as root, lots of
people have had the same problem, and their solution was "don't run as
root." Sendmail needs root permissions for some things, so this isn't
an option for me. I wonder if anyone know how to run a Java
application that needs the X-Window server as root, (or perhaps would
allow me to run a Java gui from sendmail as another user temporarily).

If you logged in as yourself (your user account) then the X server will be
7configured to prevent anyone except you from connetting GUI apps. You can
tell the X server to allow connections from any user on the local machine
by running:

xhost + localhost.

man xhost will have more details. Or you can use sudo or su to switch to the
user that does have permission to connect to the X server.

That being said, I have to go with the general concensus and say "sendmail
launching a GUI app? Yikes!"

- Rob
 
G

Gordon Beaton

I'm using sendmail 8.12.9 for a project on RedHat Fedora Core 2 on my
personal computer with a perfectly functioning X window server. Part
of this project requires me to modify sendmail to open a Java gui
application. When I attempted this originally, I got the following
error: "No X11 DISPLAY variable was set, but this program performed an
operation which requires it." Figuring that sendmail for whatever
reason unset it, I called the C function setenv() in sendmail to set
it and got the following error: "Exception in thread "main"
java.lang.InternalError: Can't connect to X11 window server using
'localhost:0.0' as the value of the DISPLAY variable." Using the
command-line imperative "-Djava.awt.headless=true" for the Java
program gives the following message: "Exception in thread "main"
java.awt.HeadlessException."

Looking into the problem, I found that when running as root, lots of
people have had the same problem, and their solution was "don't run as
root." Sendmail needs root permissions for some things, so this isn't
an option for me. I wonder if anyone know how to run a Java
application that needs the X-Window server as root, (or perhaps would
allow me to run a Java gui from sendmail as another user temporarily).

This is hardly a Java issue.

Setting the DISPLAY variable isn't enough - the process needs an
authorisation *key* to connect to the X-server. Note that the X-server
doesn't care what user you are and can't trust that information
anyway, since the connection is via a socket. "Not even" root can
connect, unless he has the right authorisation key.

The authorization key is normally created when the X server is
started, and it's stored in the display owner's .Xauthority file. You
can read it with "xauth list". The user attempting to connect needs to
add the same key to his own .Xauthority file, using "xauth add". Read
the xauth man page for more information.

A workaround that's ok for testing purposes but should be avoided
otherwise, is to disable the authorization mechanism. The display
owner can type e.g. "xhost +localhost" to let others on the localhost
connect without the authorization key.

Depending on exactly what your program needs to do, it's probably not
necessary to actually modify sendmail to start your program. Sendmail
can be configured to run external programs each time mail is
delivered, either through a .forward file in the recipient user's home
directory, or with procmail, a popular local delivery agent.

Note that there are other issues to consider when attempting to
connect to the X server from sendmail. First, there may not always be
an X server running when sendmail is running. Second, the X server is
restarted each time the user logs in and will consequently be owned by
different users at different times and have different authorisation
keys. Third, there may be more than one Xserver running at any given
time, owned by the same or different users, and there is no natural
association between the system-wide sendmail process and any of the
potentially multiple displays.

At any rate, a much cleaner solution would be to divide your code into
two parts: run the GUI manually (under control of the current logged
in user), and have it connect to sendmail and wait for instructions
from there.

/gordon
 
R

Rogan Dawes

Conrad said:
Hi.

I'm using sendmail 8.12.9 for a project on RedHat Fedora Core 2 on my
personal computer with a perfectly functioning X window server. Part
of this project requires me to modify sendmail to open a Java gui
application. When I attempted this originally, I got the following
error: "No X11 DISPLAY variable was set, but this program performed an
operation which requires it." Figuring that sendmail for whatever
reason unset it, I called the C function setenv() in sendmail to set
it and got the following error: "Exception in thread "main"
java.lang.InternalError: Can't connect to X11 window server using
'localhost:0.0' as the value of the DISPLAY variable." Using the
command-line imperative "-Djava.awt.headless=true" for the Java
program gives the following message: "Exception in thread "main"
java.awt.HeadlessException."

Looking into the problem, I found that when running as root, lots of
people have had the same problem, and their solution was "don't run as
root." Sendmail needs root permissions for some things, so this isn't
an option for me. I wonder if anyone know how to run a Java
application that needs the X-Window server as root, (or perhaps would
allow me to run a Java gui from sendmail as another user temporarily).

Thanks in advance,

Conrad Eaglehill

Another alternative might be to use socket based comms in a
client-server process. Have the GUI listen on a localhost socket for a
connection, and pop up the GUI when it receives one. your C program
passes the necessary info to the GUI, the operator makes his decision,
and returns the decision to your C program via the socket.

Your GUI effectively operates as a daemon, however it is running with
the appropriate permissions for the desktop (if it is run as the user
who owns the desktop), so it can interact with the operator/user.

If nothing else, this is probably more efficient than starting a new JVM
for every email that comes through. You incur the startup costs once
only, at initial startup. Depending on your mail volume, this may or may
not be important.

It also means that you can properly queue the emails for the operator's
attention, so that multiple emails arriving simultaneously do not all
compete for attention/focus/whatever.

Regards,

Rogan
 
C

Conrad Eaglehill

Gordon Beaton said:
A workaround that's ok for testing purposes but should be avoided
otherwise, is to disable the authorization mechanism. The display
owner can type e.g. "xhost +localhost" to let others on the localhost
connect without the authorization key.

I've actually tried this. "xhost + localhost" fromt he command-line
prior to running the mail program has no effect. Calling it from the
sendmail program itself gives "xhost: command not found."
Depending on exactly what your program needs to do, it's probably not
necessary to actually modify sendmail to start your program. Sendmail
can be configured to run external programs each time mail is
delivered, either through a .forward file in the recipient user's home
directory, or with procmail, a popular local delivery agent.

This info needs to be displayed before email is delivered, though this
was an interesting idea I hadn't considered.
Note that there are other issues to consider when attempting to
connect to the X server from sendmail. First, there may not always be
an X server running when sendmail is running.

Good point--this project assumes an X server is running, however.
Second, the X server is
restarted each time the user logs in and will consequently be owned by
different users at different times and have different authorisation
keys.

This is bad news, and may strike the project down. Why is there such a
control lock on the X server? What's the big difference between an
image displayed and text displayed?
At any rate, a much cleaner solution would be to divide your code into
two parts: run the GUI manually (under control of the current logged
in user), and have it connect to sendmail and wait for instructions
from there.

This hurdle came very late into my work--I hadn't assumed that
displaying a gui was such a big deal. I can't see why info in one
format is freely allowed but info in another format is strictly
prohibited.

But thanks for the info, Gordon. You pointed me in avenues I hadn't
considered. :)

Conrad Eaglehill
 
C

Conrad Eaglehill

Rogan Dawes said:
Another alternative might be to use socket based comms in a
client-server process. Have the GUI listen on a localhost socket for a
connection, and pop up the GUI when it receives one. your C program
passes the necessary info to the GUI, the operator makes his decision,
and returns the decision to your C program via the socket.

Your GUI effectively operates as a daemon, however it is running with
the appropriate permissions for the desktop (if it is run as the user
who owns the desktop), so it can interact with the operator/user.

If nothing else, this is probably more efficient than starting a new JVM
for every email that comes through. You incur the startup costs once
only, at initial startup. Depending on your mail volume, this may or may
not be important.

It also means that you can properly queue the emails for the operator's
attention, so that multiple emails arriving simultaneously do not all
compete for attention/focus/whatever.

Hmm...I've had more practice in sockets with C than in Java, but this
might be the way to go. I'll give this a shot. Thanks, Rogan! I think
you may have helped me out quite a bit!
Regards,

Rogan

Conrad Eaglehill
 
G

Gordon Beaton

Good point--this project assumes an X server is running, however.

Sendmail is normally started when the system boots, shortly before the
X server is started. Some time later, someone may log in. If your
modifications need to contact the X server for each mail, have you
considered what will happen if mail arrives before X is started, or
before anyone has logged in? Does it matter to your program which user
is contacted?
This info needs to be displayed before email is delivered, though
this was an interesting idea I hadn't considered.

Anything you run from .procmailrc will run immediately before each
mail is delivered, and can be used to control exactly how (or if) the
mail will be delivered, optionally modifying it in the process. You
haven't specified exactly what your software aims to do, so I don't
know whether this is a viable solution.
This is bad news, and may strike the project down. Why is there such
a control lock on the X server? What's the big difference between an
image displayed and text displayed?

The X server is a user process owned by a currently logged in user. At
any time, there can be several users logged in, and multiple X servers
(note that similar arguments hold for text-based programs as well).

This is additionally complicated by the fact that in X, client
software can run locally or remotely, and connects to the X server
using a socket. The authorisation key is necessary because anyone,
anywhere could connect to the X server otherwise. Once there, it's
simple to log keystrokes while you make a credit card payment or log
into your internet bank...

Unix and Linux are not single user systems, and solutions that assume
only a single user or a single display will run into problems.

/gordon
 
R

Rogan Dawes

Hmm...I've had more practice in sockets with C than in Java, but this
might be the way to go. I'll give this a shot. Thanks, Rogan! I think
you may have helped me out quite a bit!

My pleasure.

Note that you would need to have some kind of fall-back and retry code
for the times that the GUI is not running. You may be able to integrate
that into the sendmail infrastructure, by returning a "temporary
failure" result to the calling sendmail process, and letting it worry
about rescheduling the message for transmission.

Rogan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top