Terminal ID of terminal I/O

Source: Internet
Author: User

In most UNIX systems, the control terminal name is/dev/tty. POSIX.1, which provides a runtime function that can be used to determine the name of the control terminal.

# Include <stdio. h>

Char * ctermid (char * ptr );

Return Value: If successful, the pointer to the control terminal name is returned. If an error occurs, the pointer to a null string is returned.

If ptr is not empty, it is considered a pointer pointing to an array of at least L_ctermid bytes. The control terminal name of the process is stored in this array. The constant L_ctermid is defined in <stdio. h>. If ptr is a null pointer, this function allocates space for arrays (usually static variables. Similarly, the control terminal name of the process is stored in this array.

In both cases, the starting address of the array is returned as a function value. Because most UNIX systems use/dev/tty as the control terminal name, this function is mainly used to improve portability to other operating systems.

 

Instance: ctermid Function

Program list 18-3 POSIX.1 ctermid function implementation

# Include <stdio. h>

# Include <string. h>

 

Static char ctermid_name [L_ctermid];

 

Char *

Ctermid (char * str)

{

If (str = NULL)

Str = ctermid_name;

Return (strcpy (str, "/dev/tty");/* strcpy () returns str */

}

 

Note: because we cannot determine the size of the caller's buffer, we cannot prevent excessive use of the buffer.

 

The other two functions related to the terminal identity are isatty and ttyname. The former returns true when the file descriptor references a terminal device, while the latter returns the path name of the terminal device opened on the file descriptor.

# Include <unisd. h>

Int isatty (int filedes );

Return Value: if it is a terminal device, 1 (true) is returned, and 0 (false) is returned)

 

Char * ttyname (int filedes );

Return Value: pointer to the terminal path name. If an error occurs, NULL is returned.

 

Instance: isatty Function

Implementation of the isatty function in listing 18-4 POSIX.1

# Include <termios. h>

 

Int

Isatty (int fd)

{

Struct termios ts;

Return (tcgetattr (fd, & ts )! =-1);/* true if no error (is a tty )*/

}

 

Program list 18-5 test isatty Function

# Include "apue. h"

 

Int

Main (void)

{

Printf ("fd 0: % s \ n", isatty (0 )? "Tty": "not a tty ");

Printf ("fd 1: % s \ n", isatty (1 )? "Tty": "not a tty ");

Printf ("fd 2: % s \ n", isatty (2 )? "Tty": "not a tty ");

Exit (0 );

}

 

When running the program in the program list 18-5, we can get the following results:

 

Instance: ttyname Function

Implementation of the POSIX.1 ttyname function in the program list 18-6

# Include <sys/stat. h>

# Include <dirent. h>

# Include <limits. h>

# Include <string. h>

# Include <termios. h>

# Include <unistd. h>

# Include <stdlib. h>

 

Struct devdir {

Struct devdir * d_next;

Char * d_name;

};

 

Static struct devdir * head;

Static struct devdir * tail;

Static char pathname [_ POSIX_PATH_MAX + 1];

 

Static void

Add (char * dirname)

{

Struct devdir * ddp;

Int len;

Len = strlen (dirname );

/*

* Skip..., and/dev/fd.

*/

If (dirname [len-1] = '.') & (dirname [len-2] = '/' |

(Dirname [len-2] = '.' & dirname [len-3] = '/')))

Return;

If (strcmp (dirname, "dev/fd") = 0)

Return;

Ddp = malloc (sizeof (struct devdir ));

If (ddp = NULL)

Return;

Ddp-> d_name = strdup (dirname );

If (ddp-> d_name = NULL)

{

Free (ddp );

Return;

}

Ddp-> d_next = NULL;

If (tail = NULL)

{

Head = ddp;

Tail = ddp;

}

Else

{

Tail-> d_next = ddp;

Tail = ddp;

}

}

 

Static void

Cleanup (void)

{

Struct devdir * ddp, * nddp;

Ddp = head;

While (ddp! = NULL)

{

Nddp = ddp-> d_next;

Free (ddp-> d_name );

Free (ddp );

Ddp = nddp;

}

Head = NULL;

Tail = NULL;

}

 

Static char *

Searchdir (char * dirname, struct stat * fdstatp)

{

Struct stat devstat;

DIR * dp;

Int devlen;

Struct dirent * dirp;

Strcpy (pathname, dirname );

If (dp = opendir (dirname) = NULL)

Return (NULL );

Strcat (pathname ,"/");

Devlen = strlen (pathname );

While (dirp = readdir (dp ))! = NULL)

{

Strncpy (pathname + devlen, dirp-> d_name,

_ POSIX_PATH_MAX-devlen );

/*

* Skip aliases.

*/

If (strcmp (pathname, "/dev/stdin") = 0 |

Strcmp (pathname, "/dev/stdout") = 0 |

Strcmp (pathname, "/dev/stderr") = 0)

Continue;

If (stat (pathname, & devstat) <0)

Continue;

If (S_ISDIR (devstat. st_mode ))

{

Add (pathname );

Continue;

}

If (devstat. st_ino = fdstatp-> st_ino &&

Devstat. st_dev = fdstatp-> st_dev)/* found a match */

{

Closedir (dp );

Return (pathname );

}

}

Closedir (dp );

Return (NULL );

}

 

Char *

Ttyname (int fd)

{

Struct stat fdstat;

Struct devdir * ddp;

Char * rval;

If (isatty (fd) = 0)

Return (NULL );

If (fstat (fd, & fdstat) <0)

Return (NULL );

If (S_ISCHR (fdstat. st_mode) = 0)

Return (NULL );

 

Rval = searchdir ("/dev", & fdstat );

If (rval = NULL)

{

For (ddp = head; ddp! = NULL; ddp = ddp-> d_next)

If (rval = searchdir (ddp-> d_name, & fdstat ))! = NULL)

Break;

}

Cleanup ();

Return (rval );

}

Here, you can use the Read/dev directory to find table items with the same device number and I node number. Each file system has a unique device number (st_dev field http://www.cnblogs.com/nufangrensheng/p/3501385.html In the stat structure), and each directory item in the file system has a unique I node number (st_ino field in the stat structure ). In this function, it is assumed that the desired directory item is found when a Matched Device number and a matched I-node number are found.

The terminal name may be in the/dev subdirectory. Therefore, you need to search for the entire file system subtree under/dev. We skipped many directories that generate incorrect or strange results. They are/dev/.,/dev/.. And/dev/fd. I skipped some aliases, namely/dev/stdin,/dev/stdout, And/dev/stderr. They are symbolic links to files in the/dev/fd directory.

 

Procedure List 18-7 test the ttyname Function

# Include "apue. h"

 

Int

Main (void)

{

Char * name;

 

If (isatty (0 ))

{

Name = ttyname (0 );

If (name = NULL)

Name = "undefined ";

}

Else

{

Name = "not a tty ";

}

Printf ("fd 0: % s \ n", name );

 

If (isatty (1 ))

{

Name = ttyname (1 );

If (name = NULL)

Name = "undefined ";

}

Else

{

Name = "not a tty ";

}

Printf ("fd 1: % s \ n", name );

 

If (isatty (2 ))

{

Name = ttyname (2 );

If (name = NULL)

Name = "undefined ";

}

Else

{

Name = "not a tty ";

}

Printf ("fd 2: % s \ n", name );

Exit (0 );

}

 

Run the program to obtain:

File descriptors 0, 1, and 2 all point to the same terminal/dev/tty1.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.