[comp.lang.c++] ttyname

jonas@lkbpyr.UUCP (Jonas Heyman) (08/29/89)

Hello,

I was wondering why this work:

--------------------------------------
#include <stdio.h>
main()
{
	char *term;
	char *ttyname();
	term=ttyname();
	printf("%d",term);
}
---------------------------------------

And why this don't:
--------------------------------------
#include <stdio.h>
main()
{
	test();
}

test()
{
	char *term;
	char *ttyname();
	term=ttyname();
	printf("%d",term);
}
----------------------------------------

All the above should type out your current 'tty',example: '/dev/tty023'.

Be glad for an answer,sincerely jonas

-- 

  jonas@lkbpyr.lkb.se 

ping@cubmol.BIO.COLUMBIA.EDU (Shiping Zhang) (08/30/89)

In article <99@lkbpyr.UUCP> jonas@lkbpyr.UUCP (Jonas Heyman) writes:
>Hello,
>
>I was wondering why this work:

>#include <stdio.h>
>main()
>{
>	char *term;
>	char *ttyname();
>	term=ttyname();
>	printf("%d",term);
>}

I am wondring too because the format of printf() should be %s.





>And why this don't:

>#include <stdio.h>
>main()
>{
>	test();
>}
>
>test()
>{
>	char *term;
>	char *ttyname();
>	term=ttyname();
>	printf("%d",term);
>}

I guess because the format of printf() is incorrect.


-ping

cpcahil@virtech.UUCP (Conor P. Cahill) (08/30/89)

In article <99@lkbpyr.UUCP>, jonas@lkbpyr.UUCP (Jonas Heyman) writes:
> Hello,
> 
> I was wondering why this work:
> 

    [ example 1 with ttyname() in main() ]

> And why this don't:

    [ example 2 with ttyname() in test() called from main() ]

> 
> All the above should type out your current 'tty',example: '/dev/tty023'.
> 

This is really on of those RTFM kind of things.  ttyname() takes a
file descriptor as an argument.  Both times you were getting whatever
value happened to be on the stack at the time the ttyname was called,
you were lucky the first time (within main) probably because the
ttyname was called so early that the stack was relatively clean, but
even this is a bad assumption because other processing has already
been accomplished in the startup routines before main is called.

So add the appropriate file descriptor whose ttyname you wish to 
obtain.  (I usually use 2, to allow for redirection of stdout and
stdin and still get the ttyname.  Of course if the user redirects
all three, you're out of luck (unless you open /dev/tty and then
call ttyname() with the fd returned from the open).



-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

diamond@csl.sony.co.jp (Norman Diamond) (08/30/89)

In article <99@lkbpyr.UUCP> jonas@lkbpyr.UUCP (Jonas Heyman) writes:

->I was wondering why this works:
->#include <stdio.h>
->main()
->{
->	char *term;
->	char *ttyname();
->	term=ttyname();
->	printf("%d",term);
->}
->
->And why this doesnn't:
->#include <stdio.h>
->main()
->{
->	test();
->}
->test()
->{
->	char *term;
->	char *ttyname();
->	term=ttyname();
->	printf("%d",term);
->}

Looks to me like they should both fail.  You CAN print the decimal
value of a pointer (using "%d") but it isn't what you're asking for.
Try "%s" or maybe even "%s\n".

-- 
Norman Diamond, Sony Corporation (diamond@ws.sony.junet)
  The above opinions are inherited by your machine's init process (pid 1),
  after being disowned and orphaned.  However, if you see this at Waterloo or
  Anterior, then their administrators must have approved of these opinions.

tbecker@incas.UUCP (Thomas Becker) (08/30/89)

jonas@lkbpyr.UUCP (Jonas Heyman) writes:

>	printf("%d",term);
                ^^
yes, of course, use %d ...

Anyway, I have tried the two versions on a Sun 3/60 and found out the same.
The manpage of ttyname(3) says that the function takes a field descritor as
an argument. So I tried to call ttyname(NULL) within test(), and it worked!

>  jonas@lkbpyr.lkb.se 

Thomas

-- 
Thomas Becker --------- University of Kaiserslautern ------------- West Germany
------------ P.O. Box 3049 -------------------- D-6750 Kaiserslautern ---------
-------------------- e-mail: incas!tbecker@uklirb.uucp ------------------------
------------------------- phone: +49 631 205 3295 -----------------------------

andre@targon.UUCP (andre) (08/30/89)

In article <99@lkbpyr.UUCP> jonas@lkbpyr.UUCP (Jonas Heyman) writes:
]I was wondering why this work:
]#include <stdio.h>
]main()
]{
]       char *term;
]       char *ttyname();
]       term=ttyname();
]       printf("%d",term);
]}

Because you were lucky,

]And why this don't:
]--------------------------------------
]#include <stdio.h>
]main()
]{
]       test();
]}
]
]test()
]{
]       char *term;
]       char *ttyname();
]       term=ttyname();
]       printf("%d",term);
]}

because you were not lucky, there was something else on the stack.

The *MANUAL* says, char *ttyname(filedes).
So if you use in on stdin it will work:

term=ttyname(0);

-- 
    \---|    AAA         DDDD  It's not the kill, but the thrill of the chase.
     \  |   AA AAvv   vvDD  DD        Ketchup is a vegetable.
  /\  \ |  AAAAAAAvv vvDD  DD                    {nixbur|nixtor}!adalen.via
_/__\__\| AAA   AAAvvvDDDDDD    Andre van Dalen, uunet!hp4nl!targon!andre

vaughan@mcc.com (Paul Vaughan) (08/30/89)

   From: cpcahil@virtech.UUCP (Conor P. Cahill)

   In article <99@lkbpyr.UUCP>, jonas@lkbpyr.UUCP (Jonas Heyman) writes:
   > Hello,
   > 
   > I was wondering why this work:
   > 

       [ example 1 with ttyname() in main() ]

   > And why this don't:

       [ example 2 with ttyname() in test() called from main() ]

   > 
   > All the above should type out your current 'tty',example: '/dev/tty023'.
   > 

   This is really on of those RTFM kind of things.  ttyname() takes a
   file descriptor as an argument.  Both times you were getting whatever
   value happened to be on the stack at the time the ttyname was called,
   you were lucky the first time (within main) probably because the
   ttyname was called so early that the stack was relatively clean, but
   even this is a bad assumption because other processing has already
   been accomplished in the startup routines before main is called.

Good answer.  I was wondering why the compiler hadn't cited the
appropriate passages of TFM to him.  I guess that's something you give
up if you use <stdio.h> instead of <stream.h>.  I tried it using (the gnu
lib-g++) <stream.h> and got

io.cc:8: warning: type mismatch with previous external decl
/usr/local/gnu/lib/g++-include/std.h:204: warning: previous external
decl of `char *ttyname (int)'

The line number is different because I also bothered to declare test
first to get rid of the implicit declaration warning.  When I found
the argument passing error, I decided the original poster was
completely lost and that it wasn't worth looking at.  However, I think
it's useful to note that using <stream.h> instead of stdio.h would
have caught this one.  Not to mention that using cout instead of
printf would obviated the problem with the %d format specifier and
that the program is very clearly expressed in one line

cout << ttyname(2);


 Paul Vaughan, MCC CAD Program | ARPA: vaughan@mcc.com | Phone: [512] 338-3639
 Box 200195, Austin, TX 78720  | UUCP: ...!cs.utexas.edu!milano!cadillac!vaughan

karl@haddock.ima.isc.com (Karl Heuer) (08/31/89)

In article <1088@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>Of course if the user redirects all three, you're out of luck (unless you
>open /dev/tty and then call ttyname() with the fd returned from the open).

In which case you'll probably (depending on flavor) get the return string
"/dev/tty" rather than the true name of the terminal.  (Assuming the open
succeeds in the first place.  Not every process has a controlling terminal.)

cpcahil@virtech.UUCP (Conor P. Cahill) (08/31/89)

In article <14481@haddock.ima.isc.com>, karl@haddock.ima.isc.com (Karl Heuer) writes:
> In article <1088@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
> >Of course if the user redirects all three, you're out of luck (unless you
> >open /dev/tty and then call ttyname() with the fd returned from the open).
> 
> In which case you'll probably (depending on flavor) get the return string
> "/dev/tty" rather than the true name of the terminal.  (Assuming the open
> succeeds in the first place.  Not every process has a controlling terminal.)

I beg to differ.  If the open succeeded you will have gotten a file 
descriptor for the "controlling terminal", not /dev/tty.  The gentty driver,
which is the driver for /dev/tty,  just obtains the major/minor device
number for the current process and calls the device specific open 
routine for that device.

I can't imagine that there is a kernel out there that will return a 
file descriptor associated with /dev/tty and then re-maps it to the
appropriate device for every read and write (which it would have to 
do if the fd is associated with /dev/tty as opposed to the real terminal). 

Now that we have the file descriptor for the controlling terminal we pass
this to ttyname() which will perform an fstat
on that file descriptor and then look through the /dev directory 
for an entry that matches the device number obtained in the fstat().


-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

flaps@dgp.toronto.edu (Alan J Rosenthal) (09/01/89)

cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>I beg to differ.  If the open succeeded you will have gotten a file 
>descriptor for the "controlling terminal", not /dev/tty...
>I can't imagine that there is a kernel out there that will return a 
>file descriptor associated with /dev/tty and then re-maps it to the
>appropriate device for every read and write...

FOR F***K'S SAKE DOES NO ONE CHECK THINGS OUT BEFORE POSTING?

Script started on Thu Aug 31 16:40:46 1989
champlain.dgp% cat ttyname.c
#include <stdio.h>
#include <fcntl.h>

int main()
{
    int fd;
    char *p;
    extern char *ttyname();

    if ((fd = open("/dev/tty", O_RDWR)) < 0)
	perror("/dev/tty");
    else if ((p = ttyname(fd)) == NULL)
	fprintf(stderr, "ttyname failed\n");
    else
	printf("tty is %s\n", p);

    return(0);
}
champlain.dgp% cc ttyname.c
champlain.dgp% a.out
tty is /dev/tty
champlain.dgp% ^D
script done on Thu Aug 31 16:41:04 1989

That was on a sun running 3.5; I got the same output on an iris running sys V
whose motd says "IRIX System V Release 4D1-3.1D".

--

Posting etiquette:
When I saw Karl's posting about /dev/tty, I was surprised and I thought it was
wrong.  But I didn't just bang on my followup key.  I pressed ^Z and typed
"ttyname </dev/tty".  Much to my surprise I got the output "/dev/tty".  It's
quite simple to check before posting.  Remember that when you post hasty
replies you are wasting many people's time, especially by the volume of
followups to your followup which are generated.

ajr

cpcahil@virtech.UUCP (Conor P. Cahill) (09/01/89)

In article <1989Aug31.165349.13125@jarvis.csri.toronto.edu>, flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
> 
> Posting etiquette:
> When I saw Karl's posting about /dev/tty, I was surprised and I thought it was
> wrong.  But I didn't just bang on my followup key.  I pressed ^Z and typed
> "ttyname </dev/tty".  Much to my surprise I got the output "/dev/tty".  It's
> quite simple to check before posting.  Remember that when you post hasty
> replies you are wasting many people's time, especially by the volume of
> followups to your followup which are generated.


You are absolutely correct and I apologize for the inaccurate response.  I just
"KNEW" it had to be that way.  So much for knowing without checking.




-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

cpcahil@virtech.UUCP (Conor P. Cahill) (09/02/89)

After some more thought as to why ttyname(open("/dev/tty",0)) == "/dev/tty" 
as opposed to /dev/tty?? or whatever the name of the controlling terminal is,
I *think* I figured out the problem.

When open is called with the name "/dev/tty", it translates the name into
the inode (using the appropriate kernel routine such as namei()), and then
determines that the file to be opened is a device special file.

At this point the open calls the device specific open, which in 
this case just calls another device specific open (for the controlling
terminal).  The open code is not aware that the device that was 
actually opened is different than the one it thought was being opened and
so sets up the file table entries to point to /dev/tty.

-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

rfg@dg-rtp.dg.com (Ron Guilmette) (09/02/89)

In article <1111@virtech.UUCP> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>After some more thought as to why ttyname(open("/dev/tty",0)) == "/dev/tty" 
>...


Has this discussion got anything specifically to do with C++?

If not, could you please confine it to comp.lang.c.  Thanks.

// rfg