Home > Archive > Unix Programming > August 2006 > Does this mean I suck?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Does this mean I suck?
|
|
| K-mart Cashier 2006-08-16, 7:01 pm |
| I can't make my current session the controlling terminal. Here is what
I've attempted so far.
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LOG "/home/cdalten/telfile"
int got_signal = 0;
char signal_msg[64];
/*Some of the code is Lew's */
static void log_tel(int signo)
{
++got_signal;
sprintf(signal_msg,"got signal");
}
int main(void) {
pid_t pid;
int fd;
fd = open("/dev/tty",O_RDWR, 0);
if(fd == -1)
fprintf(stderr,"can't acquire terminal");
if( (pid = fork() ) < 0) {
fprintf(stderr, "Unable to fork process \n");
}
else if(pid == 0) {
if(setsid() < 0)
fprintf(stderr, "setsid error \n");
if( (ioctl(fd, TIOCSCTTY, NULL)) < 0)
fprintf(stderr, "error \n");
if(signal(SIGHUP, log_tel) == SIG_ERR) {
fprintf(stderr, "can't trap signal \n");
}
for(;;)
{
freopen(LOG, "w", stdout);
if(got_signal)printf("Got signal - msg is %s\n",signal_msg);
fclose(stdout);
pause();
}
} /*child*/
return 0;
}
And the ouput
$error
Under ps
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
cdalten 12305 0.0 0.1 1232 316 ? Ss 08:14 0:00 ./grex
| |
| Rainer Temme 2006-08-16, 7:01 pm |
| K-mart Cashier wrote:
> if( (ioctl(fd, TIOCSCTTY, NULL)) < 0)
> fprintf(stderr, "error \n");
> And the ouput
> $error
With a bit of google:
----------
TIOCSCTTY int arg
Make the given tty the controlling tty of the current process.
The current process must be a session leader and not have a
controlling tty already.
If this tty is already the controlling tty of a different session group
then the ioctl fails with EPERM, unless the caller is root and arg
equals 1, in which case the tty is stolen, and all processes that had it
as controlling tty lose it.
----------
You don't print out errno, so the type of error is
not displayed, but I think your proble is as described above.
Rainer
| |
| K-mart Cashier 2006-08-16, 7:01 pm |
|
Rainer Temme wrote:
> K-mart Cashier wrote:
>
>
>
>
> With a bit of google:
>
> ----------
> TIOCSCTTY int arg
>
> Make the given tty the controlling tty of the current process.
> The current process must be a session leader and not have a
> controlling tty already.
>
> If this tty is already the controlling tty of a different session group
> then the ioctl fails with EPERM, unless the caller is root and arg
> equals 1, in which case the tty is stolen, and all processes that had it
> as controlling tty lose it.
> ----------
>
> You don't print out errno, so the type of error is
> not displayed, but I think your proble is as described above.
>
> Rainer
Linux doesn't seem have EPERM.
| |
| Rainer Temme 2006-08-16, 7:01 pm |
| K-mart Cashier wrote:
> Linux doesn't seem have EPERM.
How about printing errno anyway?
Rainer
| |
| K-mart Cashier 2006-08-16, 7:01 pm |
|
Rainer Temme wrote:
> K-mart Cashier wrote:
>
>
> How about printing errno anyway?
>
> Rainer
I added the lines
#include <errno.h>
extern int errno;
then
if( (ioctl(fd, TIOCSCTTY, NULL)) < 0)
printf("Error number: %d\n", errno);
I got the following:
$./grex
$Error number: 1
| |
| K-mart Cashier 2006-08-16, 7:01 pm |
| K-mart Cashier wrote:
> Rainer Temme wrote:
>
> I added the lines
>
> #include <errno.h>
>
> extern int errno;
>
> then
> if( (ioctl(fd, TIOCSCTTY, NULL)) < 0)
> printf("Error number: %d\n", errno);
>
>
> I got the following:
> $./grex
> $Error number: 1
I don't know what the heck error code 1 means. I tried looking in the
header files and found nothing.
So I tried this approach
if( (ioctl(fd, TIOCSCTTY, NULL)) < 0) {
/*printf("Error number: %d\n", errno);*/
perror(argv[0]);
exit(1);
}
and I got the following
$gcc -g grex.c -o grex
$./grex
$./grex: Operation not permitted
| |
| Bill Pursell 2006-08-16, 7:01 pm |
|
K-mart Cashier wrote:
> Rainer Temme wrote:
>
> I added the lines
>
> #include <errno.h>
>
> extern int errno;
>
> then
> if( (ioctl(fd, TIOCSCTTY, NULL)) < 0)
> printf("Error number: %d\n", errno);
>
>
> I got the following:
> $./grex
> $Error number: 1
What you want is :
if ( ioctl(...) < 0)
perror(NULL);
In general, all of your error messages should be
replaced with a call to perror. eg: to open a FILE *, use
if ( (fp = fopen( filename, "r")) == NULL) {
perror(filename);
/* handle_error */
}
Also, after you #include <errno.h>, you shouldn't
declare errno.
And, as an aside, in your original code, the global
that you modify in the signal handler shouldn't
be declared as an int. It should either be a
volatile int, or preferrably, a sig_atomic_t.
This alerts the compiler to the fact that it may
be modified in an unexpected fashion and
prevents annoying bugs caused by compiler
optimizations.
| |
| Rainer Temme 2006-08-16, 7:01 pm |
| K-mart Cashier wrote:
[color=darkred]
[color=darkred]
[color=darkred]
> perror(argv[0]);
> $./grex: Operation not permitted
And we learn from this, that Linux indeed has EPERM ...
and now back to what I wrote in my first answer ...
the reason of EPERM are ...
Rainer
| |
| Giorgos Keramidas 2006-08-16, 7:01 pm |
| On 16 Aug 2006 09:47:24 -0700, "K-mart Cashier" <cdalten@gmail.com> wrote:
> Rainer Temme wrote:
>
> I added the lines
>
> #include <errno.h>
>
> extern int errno;
You shouldn't declare 'errno' yourself. This is the job of the
<errno.h> header.
> then
> if( (ioctl(fd, TIOCSCTTY, NULL)) < 0)
> printf("Error number: %d\n", errno);
>
>
> I got the following:
> $./grex
> $Error number: 1
Which is EPERM, as expected :)
| |
| K-mart Cashier 2006-08-16, 9:59 pm |
|
Rainer Temme wrote:
> K-mart Cashier wrote:
>
>
>
>
>
> And we learn from this, that Linux indeed has EPERM ...
> and now back to what I wrote in my first answer ...
> the reason of EPERM are ...
>
> Rainer
I thought when I called fork, the child got a unique PID to ensure that
it wasn't a process leader. Then when setsid() in the child process, it
makes the child process a session leader. In other words, I should have
gotten EPERM. Apparently I'm missing something.
| |
| K-mart Cashier 2006-08-16, 9:59 pm |
| Rainer Temme wrote:
> K-mart Cashier wrote:
>
>
>
>
>
> And we learn from this, that Linux indeed has EPERM ...
> and now back to what I wrote in my first answer ...
> the reason of EPERM are ...
>
> Rainer
I thought when I called fork(), the child got a unique PID to ensure
that it wasn't a process leader. Then when setsid() is called in the
child process, it makes the child process a session leader and makes
sure there is no controlling terminal . In other words, I shouldn't
have gotten EPERM. Apparently I'm missing something.
| |
| Bill Pursell 2006-08-17, 3:59 am |
| K-mart Cashier wrote:
> Rainer Temme wrote:
>
> I thought when I called fork(), the child got a unique PID to ensure
> that it wasn't a process leader. Then when setsid() is called in the
> child process, it makes the child process a session leader and makes
> sure there is no controlling terminal . In other words, I shouldn't
> have gotten EPERM. Apparently I'm missing something.
It's not your setsid() that is failing, but the ioctl(). The ioctl
fails not because the process isn't a session leader,
but because the tty is controlloing a different
session group. Here's the relevant text from tty_ioctl(r):
If this tty is already the controlling tty of a different
session group then the ioctl fails with EPERM, unless
the caller is root and arg equals 1, in which case
the tty is stolen, and all processes that had it as
controlling tty lose it.
Probably, what's happening is that the child is
runnning ioctl before the parent has had a chance
to exit. I added a sleep(1) to the child and your
code worked fine. (Except you really shouldn't call
sprintf in the signal handler. You can accomplish
the same thing by declaring signal_message as
a volatile char * and just doing:
signal_message = "the message", but
it's probably a better idea to keep an array
of messages and index into them with the
value of got_signal. (ie, don't just increment
got_signal, but assign a relevant value to
it in the handler.) It's a really good idea to
try to have your signal handlers do exactly
one thing: assign a global sig_atomic_t,
and nothing else.
| |
| Rainer Temme 2006-08-17, 3:59 am |
| K-mart Cashier wrote:
> I thought when I called fork(), the child got a unique PID to ensure
> that it wasn't a process leader. Then when setsid() is called in the
> child process, it makes the child process a session leader and makes
> sure there is no controlling terminal . In other words, I shouldn't
> have gotten EPERM. Apparently I'm missing something.
Yes ...
the thing is, the tty you want to use as the control-tty for the new
group is ...
- already in use as control-tty for a different group
(that is the process-group starting the child-process)
AND
- your process hasn't got root-priviledges (I just assume this)
AND
- you're not calling the ioctl with last param set to 1
ioctl(fd,TIOCSCTTY,(char*)1)
that is described as the only way to 'steal' a control-tty
which is already in use.
Rainer
| |
|
|
|
|
|