/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
/*
* ttyname(f): return "/dev/X" (where X is a relative pathname
* under /dev/), which is the name of the tty character special
* file associated with the file descriptor f, or NULL if the
* pathname cannot be found.
*
* device, file system ID, and inode numbers of the file
* descriptor parameter to those of files in the /dev/ directory.
*
* file system ID, and inode numbers, but failing to match on
* all three, settles for just a match on device numbers and
* file system ID.
*
* To achieve higher performance and more flexible functionality,
* ttyname first looks for the tty file in the directories specified
* may be qualified to specify that a partial match may be acceptable.
* This further improves performance by allowing an entry which
* exist, ttyname looks in a default list of directories. If after
* looking in the most likely places, ttyname still cannot find the
* tty file, it recursively searches thru the rest of the /dev/
* directory.
*
* In addition to the public interfaces, ttyname() & ttyname_r(), which
* do the lookup based on an open file descriptor,
* the private interface _ttyname_dev() does the lookup based on a
* device numbers.
*/
#include "lint.h"
#include "mtlib.h"
#include "libc.h"
#include "_libc_gettext.h"
#include <sys/sysmacros.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <thread.h>
#include <synch.h>
#include <errno.h>
#include <limits.h>
#include "tsd.h"
typedef struct entry {
char *name;
int flags;
} entry_t;
typedef struct special {
} spcl_t;
static const entry_t *get_pri_dirs(void);
{ "/dev", MATCH_ALL };
{ NULL, 0 }
};
};
};
char *
{
if (buflen < MAX_DEV_PATH) {
return (NULL);
}
}
/*
* POSIX.1c Draft-6 version of the function ttyname_r.
* It was implemented by Solaris 2.3.
*/
char *
{
/*
* do we need to search anything at all? (is fildes a char special tty
* file?)
*/
return (0);
}
if ((isatty(f) == 0) ||
return (0);
}
if (buflen < MAX_DEV_PATH) {
return (0);
}
}
static char *
{
int i;
int found = 0;
int dirno = 0;
int is_pts = 0;
/*
* We can't use lmutex_lock() here because we call malloc()/free()
* and _libc_gettext(). Use the brute-force callout_lock_enter().
*/
/*
* match special cases
*/
continue;
}
if (match_mask == MATCH_MM) {
goto out;
}
goto out;
}
}
/*
* additional special case: ptm clone device
* ptm devs have no entries in /dev
* if major number matches, just short circuit any further lookup
*/
spclp = &ptmspecial;
}
}
goto out;
/*
* additional special case: pty dev
*/
goto out;
/*
* search the priority directories
*/
srch_dirs = get_pri_dirs();
dev_flag = 0;
/*
* if /dev is one of the priority directories, only
* search its top level(set depth = MAX_SEARCH_DEPTH)
*/
/*
*/
is_pts = 1;
found = 1;
}
} else {
}
dirno++;
}
/*
* search the /dev/ directory, skipping priority directories
*/
if (!found)
/*
* return
*/
if (found) {
if (is_pts)
else
} else if (dev_flag)
else
return (retval);
}
/*
* POSIX.1c standard version of the function ttyname_r.
* User gets it via static ttyname_r from the header file.
*/
int
{
int nerrno = 0;
int namelen;
errno = 0;
else
if (errno == 0)
else
}
return (nerrno);
}
/*
*/
static char *
{
/*
* If we're in the global zone and the process has been
* given a pty in a non-global zone, we don't have the
* device and we can only succeed if we want to
* match the major & minor.
*/
if (match_mask != MATCH_MM)
return (NULL);
/* As we can't stat it, we return now. */
return (NULL);
else
return (buf);
}
if (match_mask == MATCH_MM) {
return (buf);
return (buf);
return (NULL);
}
/*
* Checks if the dev is a known pty master or slave device
*/
static char *
{
char prefix;
/*
*/
prefix = 't';
/*
* not a ptsl, check for a ptc
*/
/*
*/
prefix = 'p';
return (NULL);
}
/*
* check if minor number is in the known range
*/
if (dmin > MAXDEFAULTPTY)
return (NULL);
/*
* modify name based on minor number
*/
return (NULL);
if (match_mask == MATCH_MM) {
return (buf);
return (buf);
return (NULL);
}
/*
* Converts a number to a string (null terminated).
*/
static void
{
int dig = 0;
int tempi;
tempi = i;
do {
dig++;
tempi /= 10;
} while (tempi);
*ptr = '\0';
while (--dig >= 0) {
i /= 10;
}
}
/*
* srch_dir() searches directory path and all directories under it up
* to depth directories deep for a file described by a stat structure
* fsb. It puts the answer into rbuf. If a match is found on device
* number only, the file name is put into dev_rbuf and dev_flag is set.
*
* srch_dir() returns 1 if a match (on device and inode) is found,
* or 0 otherwise.
*
*/
static int
int match_mask, /* flags mask */
int depth, /* current depth (/dev = 0) */
{
char *last_comp;
int found = 0;
int dirno = 0;
/*
* do we need to search this directory? (always search /dev at depth 0)
*/
return (0);
/*
* open directory
*/
return (0);
}
*last_comp++ = '/';
/*
* read thru the directory
*/
/*
* skip "." and ".." entries, if present
*/
continue;
/*
* if the file name (path + "/" + d_name + NULL) would be too
* long, skip it
*/
continue;
continue;
continue;
/*
* single user mode.
*/
continue;
/*
* if a file is a directory and we are not too deep, recurse
*/
if (depth < MAX_SRCH_DEPTH)
else
continue;
/*
* else if it is not a directory, is it a character special
* file?
*/
int flag = 0;
found = 1;
/*
* no (inodes do not match), but save the name
* for later
*/
dev_flag = 1;
}
}
}
return (found);
}
/*
* get_pri_dirs() - returns a pointer to an array of strings, where each string
* is a priority directory name. The end of the array is marked by a NULL
* pointer. The priority directories' names are obtained from the file
* list of directories.
*
* then parsed into strings of priority directory names, omitting comments and
* blank lines.
*
*/
static const entry_t *
get_pri_dirs(void)
{
/*
*/
return (def_srch_dirs);
return (def_srch_dirs);
}
/*
* size & modification time match
* no need to reread TTYSRCH
* just return old pointer
*/
return (dir_vec);
}
}
}
return ((entry_t *)def_srch_dirs);
}
/*
* ensure newline termination for buffer. Add an extra
* entry to dir_vec for null terminator
*/
*ebuf++ = '\n';
if (*buf == '\n')
++sz;
}
return (def_srch_dirs);
}
state = START_STATE;
switch (state) {
case START_STATE:
if (*buf == COMMENT_CHAR) {
break;
}
break;
case COMMENT_STATE:
state = START_STATE;
break;
case DIRNAME_STATE:
state = CHECK_STATE;
*buf = '\0';
/* skip trailing white space */
state = FLAG_STATE;
*buf = '\0';
}
break;
case FLAG_STATE:
switch (*buf) {
case 'M':
break;
case 'F':
break;
case 'I':
break;
case EOLN_CHAR:
state = CHECK_STATE;
break;
}
break;
case CHECK_STATE:
if (tfd >= 0) {
}
} else {
char *slash;
while (*slash == '/')
*slash-- = '\0';
vec++;
}
state = START_STATE;
/*
* This state does not consume a character, so
* reposition the pointer.
*/
buf--;
break;
}
}
return (dir_vec);
}
char *
ttyname(int f)
{
return (NULL);
}