17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
513b62818Sraf * Common Development and Distribution License (the "License").
613b62818Sraf * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
2113b62818Sraf
227c478bd9Sstevel@tonic-gate /*
237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * ttyname(f): return "/dev/X" (where X is a relative pathname
327c478bd9Sstevel@tonic-gate * under /dev/), which is the name of the tty character special
337c478bd9Sstevel@tonic-gate * file associated with the file descriptor f, or NULL if the
347c478bd9Sstevel@tonic-gate * pathname cannot be found.
357c478bd9Sstevel@tonic-gate *
367c478bd9Sstevel@tonic-gate * Ttyname tries to find the tty file by matching major/minor
377c478bd9Sstevel@tonic-gate * device, file system ID, and inode numbers of the file
387c478bd9Sstevel@tonic-gate * descriptor parameter to those of files in the /dev/ directory.
397c478bd9Sstevel@tonic-gate *
407c478bd9Sstevel@tonic-gate * It attempts to find a match on major/minor device numbers,
417c478bd9Sstevel@tonic-gate * file system ID, and inode numbers, but failing to match on
427c478bd9Sstevel@tonic-gate * all three, settles for just a match on device numbers and
437c478bd9Sstevel@tonic-gate * file system ID.
447c478bd9Sstevel@tonic-gate *
457c478bd9Sstevel@tonic-gate * To achieve higher performance and more flexible functionality,
467c478bd9Sstevel@tonic-gate * ttyname first looks for the tty file in the directories specified
477c478bd9Sstevel@tonic-gate * in the configuration file /etc/ttysrch. Entries in /etc/ttysrch
487c478bd9Sstevel@tonic-gate * may be qualified to specify that a partial match may be acceptable.
497c478bd9Sstevel@tonic-gate * This further improves performance by allowing an entry which
507c478bd9Sstevel@tonic-gate * matches major/minor and file system ID, but not inode number
517c478bd9Sstevel@tonic-gate * without searching the entire /dev tree. If /etc/ttysrch does not
527c478bd9Sstevel@tonic-gate * exist, ttyname looks in a default list of directories. If after
537c478bd9Sstevel@tonic-gate * looking in the most likely places, ttyname still cannot find the
547c478bd9Sstevel@tonic-gate * tty file, it recursively searches thru the rest of the /dev/
557c478bd9Sstevel@tonic-gate * directory.
567c478bd9Sstevel@tonic-gate *
577c478bd9Sstevel@tonic-gate * In addition to the public interfaces, ttyname() & ttyname_r(), which
587c478bd9Sstevel@tonic-gate * do the lookup based on an open file descriptor,
597c478bd9Sstevel@tonic-gate * the private interface _ttyname_dev() does the lookup based on a
607c478bd9Sstevel@tonic-gate * major/minor device. It follows the same order of lookup rules and
617c478bd9Sstevel@tonic-gate * returns similar information, but matches on just the major/minor
627c478bd9Sstevel@tonic-gate * device numbers.
637c478bd9Sstevel@tonic-gate */
647c478bd9Sstevel@tonic-gate
657257d1b4Sraf #pragma weak _ttyname = ttyname
667c478bd9Sstevel@tonic-gate
677257d1b4Sraf #include "lint.h"
687c478bd9Sstevel@tonic-gate #include "mtlib.h"
697c478bd9Sstevel@tonic-gate #include "libc.h"
707c478bd9Sstevel@tonic-gate #include "_libc_gettext.h"
717c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
727c478bd9Sstevel@tonic-gate #include <sys/types.h>
737c478bd9Sstevel@tonic-gate #include <dirent.h>
747c478bd9Sstevel@tonic-gate #include <fcntl.h>
757c478bd9Sstevel@tonic-gate #include <sys/stat.h>
767c478bd9Sstevel@tonic-gate #include <stdlib.h>
777c478bd9Sstevel@tonic-gate #include <ctype.h>
787c478bd9Sstevel@tonic-gate #include <string.h>
797c478bd9Sstevel@tonic-gate #include <stdio.h>
807c478bd9Sstevel@tonic-gate #include <unistd.h>
817c478bd9Sstevel@tonic-gate #include <thread.h>
827c478bd9Sstevel@tonic-gate #include <synch.h>
837c478bd9Sstevel@tonic-gate #include <errno.h>
847c478bd9Sstevel@tonic-gate #include <limits.h>
857c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
867c478bd9Sstevel@tonic-gate #include "tsd.h"
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate typedef struct entry {
897c478bd9Sstevel@tonic-gate char *name;
907c478bd9Sstevel@tonic-gate int flags;
917c478bd9Sstevel@tonic-gate } entry_t;
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate typedef struct special {
947c478bd9Sstevel@tonic-gate const char *spcl_name; /* device name */
957c478bd9Sstevel@tonic-gate dev_t spcl_rdev; /* matching major/minor devnum */
967c478bd9Sstevel@tonic-gate dev_t spcl_fsdev; /* devnum of containing FS */
977c478bd9Sstevel@tonic-gate ino_t spcl_inum; /* inum of entry in FS */
987c478bd9Sstevel@tonic-gate } spcl_t;
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate static int srch_dir(const entry_t path, int match_mask, int depth,
1017c478bd9Sstevel@tonic-gate const entry_t skip_dirs[], struct stat64 *fsb);
1027c478bd9Sstevel@tonic-gate static const entry_t *get_pri_dirs(void);
1037c478bd9Sstevel@tonic-gate static char *ispts(struct stat64 *fsb, int match_mask);
1047c478bd9Sstevel@tonic-gate static char *ispty(struct stat64 *fsb, int match_mask);
1057c478bd9Sstevel@tonic-gate static void itoa(int i, char *ptr);
1067c478bd9Sstevel@tonic-gate static char *_ttyname_common(struct stat64 *fsp, char *buffer,
1077c478bd9Sstevel@tonic-gate uint_t match_mask);
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate #define MAX_DEV_PATH TTYNAME_MAX
1117c478bd9Sstevel@tonic-gate #define MAX_SRCH_DEPTH 4
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate #define MATCH_MM 1
1147c478bd9Sstevel@tonic-gate #define MATCH_FS 2
1157c478bd9Sstevel@tonic-gate #define MATCH_INO 4
1167c478bd9Sstevel@tonic-gate #define MATCH_ALL 7
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate #define DEV "/dev"
1197c478bd9Sstevel@tonic-gate #define TTYSRCH "/etc/ttysrch"
1207c478bd9Sstevel@tonic-gate #define PTS "/dev/pts"
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate static const entry_t dev_dir =
1237c478bd9Sstevel@tonic-gate { "/dev", MATCH_ALL };
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate static const entry_t def_srch_dirs[] = { /* default search list */
1267c478bd9Sstevel@tonic-gate { "/dev/pts", MATCH_ALL },
127*aecfc01dSrui zang - Sun Microsystems - Beijing China { "/dev/vt", MATCH_ALL },
1287c478bd9Sstevel@tonic-gate { "/dev/term", MATCH_ALL },
1297c478bd9Sstevel@tonic-gate { "/dev/zcons", MATCH_ALL },
1307c478bd9Sstevel@tonic-gate { NULL, 0 }
1317c478bd9Sstevel@tonic-gate };
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate static char *dir_buf; /* directory buffer for ttysrch body */
1347c478bd9Sstevel@tonic-gate static entry_t *dir_vec; /* directory vector for ttysrch ptrs */
1357c478bd9Sstevel@tonic-gate static size_t dir_size; /* ttysrch file size */
1367c478bd9Sstevel@tonic-gate static timestruc_t dir_mtim; /* ttysrch file modification time */
1377c478bd9Sstevel@tonic-gate static char rbuf[MAX_DEV_PATH]; /* perfect match file name */
1387c478bd9Sstevel@tonic-gate static char dev_rbuf[MAX_DEV_PATH]; /* partial match file name */
1397c478bd9Sstevel@tonic-gate static int dev_flag; /* if set, dev + rdev match was found */
1407c478bd9Sstevel@tonic-gate static spcl_t special_case[] = {
1417c478bd9Sstevel@tonic-gate "/dev/tty", 0, 0, 0,
1427c478bd9Sstevel@tonic-gate "/dev/console", 0, 0, 0,
1437c478bd9Sstevel@tonic-gate "/dev/conslog", 0, 0, 0,
1447c478bd9Sstevel@tonic-gate "/dev/systty", 0, 0, 0,
14531c0bba7SRoger A. Faulkner "/dev/wscons", 0, 0, 0,
14631c0bba7SRoger A. Faulkner "/dev/msglog", 0, 0, 0,
1477c478bd9Sstevel@tonic-gate };
1487c478bd9Sstevel@tonic-gate #define NUMSPECIAL (sizeof (special_case) / sizeof (spcl_t))
1497c478bd9Sstevel@tonic-gate static spcl_t ptmspecial = {
1507c478bd9Sstevel@tonic-gate "/dev/ptmx", 0, 0, 0
1517c478bd9Sstevel@tonic-gate };
1527c478bd9Sstevel@tonic-gate static dev_t ptcdev = NODEV;
1537c478bd9Sstevel@tonic-gate static dev_t ptsldev = NODEV;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate char *
_ttyname_dev(dev_t rdev,char * buffer,size_t buflen)1567c478bd9Sstevel@tonic-gate _ttyname_dev(dev_t rdev, char *buffer, size_t buflen)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate struct stat64 fsb;
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate fsb.st_rdev = rdev;
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate if (buflen < MAX_DEV_PATH) {
1637c478bd9Sstevel@tonic-gate errno = ERANGE;
1647c478bd9Sstevel@tonic-gate return (NULL);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate return (_ttyname_common(&fsb, buffer, MATCH_MM));
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /*
1717c478bd9Sstevel@tonic-gate * POSIX.1c Draft-6 version of the function ttyname_r.
1727c478bd9Sstevel@tonic-gate * It was implemented by Solaris 2.3.
1737c478bd9Sstevel@tonic-gate */
1747c478bd9Sstevel@tonic-gate char *
ttyname_r(int f,char * buffer,int buflen)1757257d1b4Sraf ttyname_r(int f, char *buffer, int buflen)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate struct stat64 fsb; /* what we are searching for */
1787c478bd9Sstevel@tonic-gate /*
1797c478bd9Sstevel@tonic-gate * do we need to search anything at all? (is fildes a char special tty
1807c478bd9Sstevel@tonic-gate * file?)
1817c478bd9Sstevel@tonic-gate */
1827c478bd9Sstevel@tonic-gate if (fstat64(f, &fsb) < 0) {
1837c478bd9Sstevel@tonic-gate errno = EBADF;
1847c478bd9Sstevel@tonic-gate return (0);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate if ((isatty(f) == 0) ||
1877c478bd9Sstevel@tonic-gate ((fsb.st_mode & S_IFMT) != S_IFCHR)) {
1887c478bd9Sstevel@tonic-gate errno = ENOTTY;
1897c478bd9Sstevel@tonic-gate return (0);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate if (buflen < MAX_DEV_PATH) {
1937c478bd9Sstevel@tonic-gate errno = ERANGE;
1947c478bd9Sstevel@tonic-gate return (0);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate return (_ttyname_common(&fsb, buffer, MATCH_ALL));
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate static char *
_ttyname_common(struct stat64 * fsp,char * buffer,uint_t match_mask)2017c478bd9Sstevel@tonic-gate _ttyname_common(struct stat64 *fsp, char *buffer, uint_t match_mask)
2027c478bd9Sstevel@tonic-gate {
2037c478bd9Sstevel@tonic-gate struct stat64 tfsb;
2047c478bd9Sstevel@tonic-gate const entry_t *srch_dirs; /* priority directories */
2057c478bd9Sstevel@tonic-gate spcl_t *spclp;
2067c478bd9Sstevel@tonic-gate int i;
2077c478bd9Sstevel@tonic-gate int found = 0;
2087c478bd9Sstevel@tonic-gate int dirno = 0;
2097c478bd9Sstevel@tonic-gate int is_pts = 0;
2107c478bd9Sstevel@tonic-gate char *retval = NULL;
2117c478bd9Sstevel@tonic-gate char *pt = NULL;
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate * We can't use lmutex_lock() here because we call malloc()/free()
21598c1a6b4Sraf * and _libc_gettext(). Use the brute-force callout_lock_enter().
2167c478bd9Sstevel@tonic-gate */
21798c1a6b4Sraf callout_lock_enter();
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate * match special cases
2217c478bd9Sstevel@tonic-gate */
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate for (spclp = special_case, i = 0; i < NUMSPECIAL; spclp++, i++) {
2247c478bd9Sstevel@tonic-gate if ((spclp->spcl_inum | spclp->spcl_fsdev |
2257c478bd9Sstevel@tonic-gate spclp->spcl_rdev) == 0) {
2267c478bd9Sstevel@tonic-gate if (stat64(spclp->spcl_name, &tfsb) != 0)
2277c478bd9Sstevel@tonic-gate continue;
2287c478bd9Sstevel@tonic-gate spclp->spcl_rdev = tfsb.st_rdev;
2297c478bd9Sstevel@tonic-gate spclp->spcl_fsdev = tfsb.st_dev;
2307c478bd9Sstevel@tonic-gate spclp->spcl_inum = tfsb.st_ino;
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate if (match_mask == MATCH_MM) {
2337c478bd9Sstevel@tonic-gate if (spclp->spcl_rdev == fsp->st_rdev) {
2347c478bd9Sstevel@tonic-gate retval = strcpy(rbuf, spclp->spcl_name);
2357c478bd9Sstevel@tonic-gate goto out;
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate } else if (spclp->spcl_fsdev == fsp->st_dev &&
2387c478bd9Sstevel@tonic-gate spclp->spcl_rdev == fsp->st_rdev &&
2397c478bd9Sstevel@tonic-gate spclp->spcl_inum == fsp->st_ino) {
2407c478bd9Sstevel@tonic-gate retval = strcpy(rbuf, spclp->spcl_name);
2417c478bd9Sstevel@tonic-gate goto out;
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate * additional special case: ptm clone device
2467c478bd9Sstevel@tonic-gate * ptm devs have no entries in /dev
2477c478bd9Sstevel@tonic-gate * if major number matches, just short circuit any further lookup
2487c478bd9Sstevel@tonic-gate * NOTE: the minor number of /dev/ptmx is the ptm major number
2497c478bd9Sstevel@tonic-gate */
2507c478bd9Sstevel@tonic-gate spclp = &ptmspecial;
2517c478bd9Sstevel@tonic-gate if ((spclp->spcl_inum | spclp->spcl_fsdev | spclp->spcl_rdev) == 0) {
2527c478bd9Sstevel@tonic-gate if (stat64(spclp->spcl_name, &tfsb) == 0) {
2537c478bd9Sstevel@tonic-gate spclp->spcl_rdev = tfsb.st_rdev;
2547c478bd9Sstevel@tonic-gate spclp->spcl_fsdev = tfsb.st_dev;
2557c478bd9Sstevel@tonic-gate spclp->spcl_inum = tfsb.st_ino;
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate if ((spclp->spcl_rdev != 0) &&
2597c478bd9Sstevel@tonic-gate (minor(spclp->spcl_rdev) == major(fsp->st_rdev)))
2607c478bd9Sstevel@tonic-gate goto out;
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate * additional special case: pty dev
2647c478bd9Sstevel@tonic-gate * one of the known default pairs of /dev/ptyXX or /dev/ttyXX
2657c478bd9Sstevel@tonic-gate */
2667c478bd9Sstevel@tonic-gate if ((retval = ispty(fsp, match_mask)) != NULL)
2677c478bd9Sstevel@tonic-gate goto out;
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate /*
2707c478bd9Sstevel@tonic-gate * search the priority directories
2717c478bd9Sstevel@tonic-gate */
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate srch_dirs = get_pri_dirs();
2757c478bd9Sstevel@tonic-gate dev_flag = 0;
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate while ((!found) && (srch_dirs[dirno].name != NULL)) {
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate /*
2807c478bd9Sstevel@tonic-gate * if /dev is one of the priority directories, only
2817c478bd9Sstevel@tonic-gate * search its top level(set depth = MAX_SEARCH_DEPTH)
2827c478bd9Sstevel@tonic-gate */
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * Is /dev/pts then just do a quick check. We don't have
2867c478bd9Sstevel@tonic-gate * to stat the entire /dev/pts dir.
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate if (strcmp(PTS, srch_dirs[dirno].name) == NULL) {
2897c478bd9Sstevel@tonic-gate if ((pt = ispts(fsp, match_mask)) != NULL) {
2907c478bd9Sstevel@tonic-gate is_pts = 1;
2917c478bd9Sstevel@tonic-gate found = 1;
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate } else {
2947c478bd9Sstevel@tonic-gate found = srch_dir(srch_dirs[dirno], match_mask,
29511a1a29eSlt200341 ((strcmp(srch_dirs[dirno].name, dev_dir.name)
29611a1a29eSlt200341 == 0) ? MAX_SRCH_DEPTH : 1), 0, fsp);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate dirno++;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate /*
3027c478bd9Sstevel@tonic-gate * search the /dev/ directory, skipping priority directories
3037c478bd9Sstevel@tonic-gate */
3047c478bd9Sstevel@tonic-gate if (!found)
3057c478bd9Sstevel@tonic-gate found = srch_dir(dev_dir, match_mask, 0, srch_dirs, fsp);
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate * return
3107c478bd9Sstevel@tonic-gate */
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate if (found) {
3137c478bd9Sstevel@tonic-gate if (is_pts)
3147c478bd9Sstevel@tonic-gate retval = pt;
3157c478bd9Sstevel@tonic-gate else
3167c478bd9Sstevel@tonic-gate retval = rbuf;
3177c478bd9Sstevel@tonic-gate } else if (dev_flag)
3187c478bd9Sstevel@tonic-gate retval = dev_rbuf;
3197c478bd9Sstevel@tonic-gate else
3207c478bd9Sstevel@tonic-gate retval = NULL;
3217c478bd9Sstevel@tonic-gate out: retval = (retval ? strcpy(buffer, retval) : NULL);
32298c1a6b4Sraf callout_lock_exit();
3237c478bd9Sstevel@tonic-gate return (retval);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate /*
3277c478bd9Sstevel@tonic-gate * POSIX.1c standard version of the function ttyname_r.
3287c478bd9Sstevel@tonic-gate * User gets it via static ttyname_r from the header file.
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate int
__posix_ttyname_r(int fildes,char * name,size_t namesize)3317c478bd9Sstevel@tonic-gate __posix_ttyname_r(int fildes, char *name, size_t namesize)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate int nerrno = 0;
3347c478bd9Sstevel@tonic-gate int oerrno = errno;
3357c478bd9Sstevel@tonic-gate int namelen;
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate errno = 0;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate if (namesize > INT_MAX)
3407c478bd9Sstevel@tonic-gate namelen = INT_MAX;
3417c478bd9Sstevel@tonic-gate else
3427c478bd9Sstevel@tonic-gate namelen = (int)namesize;
3437c478bd9Sstevel@tonic-gate
3447257d1b4Sraf if (ttyname_r(fildes, name, namelen) == NULL) {
3457c478bd9Sstevel@tonic-gate if (errno == 0)
3467c478bd9Sstevel@tonic-gate nerrno = EINVAL;
3477c478bd9Sstevel@tonic-gate else
3487c478bd9Sstevel@tonic-gate nerrno = errno;
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate errno = oerrno;
3517c478bd9Sstevel@tonic-gate return (nerrno);
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate /*
3557c478bd9Sstevel@tonic-gate * Checks if the name is under /dev/pts directory
3567c478bd9Sstevel@tonic-gate */
3577c478bd9Sstevel@tonic-gate static char *
ispts(struct stat64 * fsb,int match_mask)3587c478bd9Sstevel@tonic-gate ispts(struct stat64 *fsb, int match_mask)
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate static char buf[MAX_DEV_PATH];
3617c478bd9Sstevel@tonic-gate struct stat64 stb;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate (void) strcpy(buf, "/dev/pts/");
3647c478bd9Sstevel@tonic-gate itoa(minor(fsb->st_rdev), buf+strlen(buf));
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate if (stat64(buf, &stb) != 0)
3677c478bd9Sstevel@tonic-gate return (NULL);
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate if (match_mask == MATCH_MM) {
3707c478bd9Sstevel@tonic-gate if (stb.st_rdev == fsb->st_rdev)
3717c478bd9Sstevel@tonic-gate return (buf);
37211a1a29eSlt200341 } else if (stb.st_rdev == fsb->st_rdev && stb.st_dev == fsb->st_dev &&
3737c478bd9Sstevel@tonic-gate stb.st_ino == fsb->st_ino)
3747c478bd9Sstevel@tonic-gate return (buf);
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate return (NULL);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate /*
3807c478bd9Sstevel@tonic-gate * Checks if the dev is a known pty master or slave device
3817c478bd9Sstevel@tonic-gate */
3827c478bd9Sstevel@tonic-gate #define MAXDEFAULTPTY 48
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate static char *
ispty(struct stat64 * fsb,int match_mask)3857c478bd9Sstevel@tonic-gate ispty(struct stat64 *fsb, int match_mask)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate static char buf[16]; /* big enough for "/dev/XtyXX" */
3887c478bd9Sstevel@tonic-gate struct stat64 stb;
3897c478bd9Sstevel@tonic-gate minor_t dmin;
3907c478bd9Sstevel@tonic-gate char prefix;
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate if (ptsldev == NODEV && stat64("/dev/ttyp0", &stb) == 0)
3937c478bd9Sstevel@tonic-gate ptsldev = stb.st_rdev;
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate * check for a ptsl dev (/dev/ttyXX)
3977c478bd9Sstevel@tonic-gate */
3987c478bd9Sstevel@tonic-gate prefix = 't';
3997c478bd9Sstevel@tonic-gate if (major(fsb->st_rdev) != major(ptsldev)) {
4007c478bd9Sstevel@tonic-gate /*
4017c478bd9Sstevel@tonic-gate * not a ptsl, check for a ptc
4027c478bd9Sstevel@tonic-gate */
4037c478bd9Sstevel@tonic-gate if (ptcdev == NODEV && stat64("/dev/ptyp0", &stb) == 0)
4047c478bd9Sstevel@tonic-gate ptcdev = stb.st_rdev;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate * check for a ptc dev (/dev/ptyXX)
4087c478bd9Sstevel@tonic-gate */
4097c478bd9Sstevel@tonic-gate prefix = 'p';
4107c478bd9Sstevel@tonic-gate if (major(fsb->st_rdev) != major(ptcdev))
4117c478bd9Sstevel@tonic-gate return (NULL);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate * check if minor number is in the known range
4167c478bd9Sstevel@tonic-gate */
4177c478bd9Sstevel@tonic-gate dmin = minor(fsb->st_rdev);
4187c478bd9Sstevel@tonic-gate if (dmin > MAXDEFAULTPTY)
4197c478bd9Sstevel@tonic-gate return (NULL);
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate * modify name based on minor number
4237c478bd9Sstevel@tonic-gate */
4247c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/dev/%cty%c%c",
4257c478bd9Sstevel@tonic-gate prefix, 'p' + dmin / 16, "0123456789abcdef"[dmin % 16]);
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate if (stat64(buf, &stb) != 0)
4287c478bd9Sstevel@tonic-gate return (NULL);
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate if (match_mask == MATCH_MM) {
4317c478bd9Sstevel@tonic-gate if (stb.st_rdev == fsb->st_rdev)
4327c478bd9Sstevel@tonic-gate return (buf);
4337c478bd9Sstevel@tonic-gate } else if (stb.st_rdev == fsb->st_rdev &&
4347c478bd9Sstevel@tonic-gate stb.st_dev == fsb->st_dev &&
4357c478bd9Sstevel@tonic-gate stb.st_ino == fsb->st_ino)
4367c478bd9Sstevel@tonic-gate return (buf);
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate return (NULL);
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate /*
4437c478bd9Sstevel@tonic-gate * Converts a number to a string (null terminated).
4447c478bd9Sstevel@tonic-gate */
4457c478bd9Sstevel@tonic-gate static void
itoa(int i,char * ptr)4467c478bd9Sstevel@tonic-gate itoa(int i, char *ptr)
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate int dig = 0;
4497c478bd9Sstevel@tonic-gate int tempi;
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate tempi = i;
4527c478bd9Sstevel@tonic-gate do {
4537c478bd9Sstevel@tonic-gate dig++;
4547c478bd9Sstevel@tonic-gate tempi /= 10;
4557c478bd9Sstevel@tonic-gate } while (tempi);
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate ptr += dig;
4587c478bd9Sstevel@tonic-gate *ptr = '\0';
4597c478bd9Sstevel@tonic-gate while (--dig >= 0) {
4607c478bd9Sstevel@tonic-gate *(--ptr) = i % 10 + '0';
4617c478bd9Sstevel@tonic-gate i /= 10;
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate /*
4667c478bd9Sstevel@tonic-gate * srch_dir() searches directory path and all directories under it up
4677c478bd9Sstevel@tonic-gate * to depth directories deep for a file described by a stat structure
4687c478bd9Sstevel@tonic-gate * fsb. It puts the answer into rbuf. If a match is found on device
4697c478bd9Sstevel@tonic-gate * number only, the file name is put into dev_rbuf and dev_flag is set.
4707c478bd9Sstevel@tonic-gate *
4717c478bd9Sstevel@tonic-gate * srch_dir() returns 1 if a match (on device and inode) is found,
4727c478bd9Sstevel@tonic-gate * or 0 otherwise.
4737c478bd9Sstevel@tonic-gate *
4747c478bd9Sstevel@tonic-gate */
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate static int
srch_dir(const entry_t path,int match_mask,int depth,const entry_t skip_dirs[],struct stat64 * fsb)4777c478bd9Sstevel@tonic-gate srch_dir(const entry_t path, /* current path */
4787c478bd9Sstevel@tonic-gate int match_mask, /* flags mask */
4797c478bd9Sstevel@tonic-gate int depth, /* current depth (/dev = 0) */
4807c478bd9Sstevel@tonic-gate const entry_t skip_dirs[], /* directories not needing searching */
4817c478bd9Sstevel@tonic-gate struct stat64 *fsb) /* the file being searched for */
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate DIR *dirp;
4847c478bd9Sstevel@tonic-gate struct dirent64 *direntp;
4857c478bd9Sstevel@tonic-gate struct stat64 tsb;
4867c478bd9Sstevel@tonic-gate char file_name[MAX_DEV_PATH];
4877c478bd9Sstevel@tonic-gate entry_t file;
4887c478bd9Sstevel@tonic-gate char *last_comp;
4897c478bd9Sstevel@tonic-gate int found = 0;
4907c478bd9Sstevel@tonic-gate int dirno = 0;
4917c478bd9Sstevel@tonic-gate size_t path_len;
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate file.name = file_name;
4947c478bd9Sstevel@tonic-gate file.flags = path.flags & match_mask;
4957c478bd9Sstevel@tonic-gate if (file.flags == 0)
4967c478bd9Sstevel@tonic-gate file.flags = match_mask;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate /*
4997c478bd9Sstevel@tonic-gate * do we need to search this directory? (always search /dev at depth 0)
5007c478bd9Sstevel@tonic-gate */
5017c478bd9Sstevel@tonic-gate if ((skip_dirs != NULL) && (depth != 0))
5027c478bd9Sstevel@tonic-gate while (skip_dirs[dirno].name != NULL)
5037c478bd9Sstevel@tonic-gate if (strcmp(skip_dirs[dirno++].name, path.name) == 0)
5047c478bd9Sstevel@tonic-gate return (0);
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate /*
5077c478bd9Sstevel@tonic-gate * open directory
5087c478bd9Sstevel@tonic-gate */
5097c478bd9Sstevel@tonic-gate if ((dirp = opendir(path.name)) == NULL) {
5107c478bd9Sstevel@tonic-gate return (0);
5117c478bd9Sstevel@tonic-gate }
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate path_len = strlen(path.name);
5147c478bd9Sstevel@tonic-gate (void) strcpy(file_name, path.name);
5157c478bd9Sstevel@tonic-gate last_comp = file_name + path_len;
5167c478bd9Sstevel@tonic-gate *last_comp++ = '/';
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate * read thru the directory
5207c478bd9Sstevel@tonic-gate */
5217c478bd9Sstevel@tonic-gate while ((!found) && ((direntp = readdir64(dirp)) != NULL)) {
52213b62818Sraf /*
52313b62818Sraf * skip "." and ".." entries, if present
52413b62818Sraf */
52513b62818Sraf if (direntp->d_name[0] == '.' &&
52613b62818Sraf (strcmp(direntp->d_name, ".") == 0 ||
52713b62818Sraf strcmp(direntp->d_name, "..") == 0))
52813b62818Sraf continue;
5297c478bd9Sstevel@tonic-gate
5307c478bd9Sstevel@tonic-gate /*
5317c478bd9Sstevel@tonic-gate * if the file name (path + "/" + d_name + NULL) would be too
5327c478bd9Sstevel@tonic-gate * long, skip it
5337c478bd9Sstevel@tonic-gate */
5347c478bd9Sstevel@tonic-gate if ((path_len + strlen(direntp->d_name) + 2) > MAX_DEV_PATH)
5357c478bd9Sstevel@tonic-gate continue;
5367c478bd9Sstevel@tonic-gate
53713b62818Sraf (void) strcpy(last_comp, direntp->d_name);
5387c478bd9Sstevel@tonic-gate if (stat64(file_name, &tsb) < 0)
5397c478bd9Sstevel@tonic-gate continue;
5407c478bd9Sstevel@tonic-gate
541*aecfc01dSrui zang - Sun Microsystems - Beijing China if (strcmp(file_name, "/dev/vt/active") == 0)
542*aecfc01dSrui zang - Sun Microsystems - Beijing China continue;
543*aecfc01dSrui zang - Sun Microsystems - Beijing China
5447c478bd9Sstevel@tonic-gate /*
54511a1a29eSlt200341 * skip "/dev/syscon" because it may be an invalid link after
54611a1a29eSlt200341 * single user mode.
54711a1a29eSlt200341 */
54811a1a29eSlt200341 if (strcmp(file_name, "/dev/syscon") == 0)
54911a1a29eSlt200341 continue;
55011a1a29eSlt200341
55111a1a29eSlt200341 /*
5527c478bd9Sstevel@tonic-gate * if a file is a directory and we are not too deep, recurse
5537c478bd9Sstevel@tonic-gate */
5547c478bd9Sstevel@tonic-gate if ((tsb.st_mode & S_IFMT) == S_IFDIR)
5557c478bd9Sstevel@tonic-gate if (depth < MAX_SRCH_DEPTH)
5567c478bd9Sstevel@tonic-gate found = srch_dir(file, match_mask, depth+1,
5577c478bd9Sstevel@tonic-gate skip_dirs, fsb);
5587c478bd9Sstevel@tonic-gate else
5597c478bd9Sstevel@tonic-gate continue;
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate /*
5627c478bd9Sstevel@tonic-gate * else if it is not a directory, is it a character special
5637c478bd9Sstevel@tonic-gate * file?
5647c478bd9Sstevel@tonic-gate */
5657c478bd9Sstevel@tonic-gate else if ((tsb.st_mode & S_IFMT) == S_IFCHR) {
5667c478bd9Sstevel@tonic-gate int flag = 0;
5677c478bd9Sstevel@tonic-gate if (tsb.st_dev == fsb->st_dev)
5687c478bd9Sstevel@tonic-gate flag |= MATCH_FS;
5697c478bd9Sstevel@tonic-gate if (tsb.st_rdev == fsb->st_rdev)
5707c478bd9Sstevel@tonic-gate flag |= MATCH_MM;
5717c478bd9Sstevel@tonic-gate if (tsb.st_ino == fsb->st_ino)
5727c478bd9Sstevel@tonic-gate flag |= MATCH_INO;
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate if ((flag & file.flags) == file.flags) {
5757c478bd9Sstevel@tonic-gate (void) strcpy(rbuf, file.name);
5767c478bd9Sstevel@tonic-gate found = 1;
5777c478bd9Sstevel@tonic-gate } else if ((flag & (MATCH_MM | MATCH_FS)) ==
5787c478bd9Sstevel@tonic-gate (MATCH_MM | MATCH_FS)) {
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate /*
5817c478bd9Sstevel@tonic-gate * no (inodes do not match), but save the name
5827c478bd9Sstevel@tonic-gate * for later
5837c478bd9Sstevel@tonic-gate */
5847c478bd9Sstevel@tonic-gate (void) strcpy(dev_rbuf, file.name);
5857c478bd9Sstevel@tonic-gate dev_flag = 1;
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate (void) closedir(dirp);
5907c478bd9Sstevel@tonic-gate return (found);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate /*
5957c478bd9Sstevel@tonic-gate * get_pri_dirs() - returns a pointer to an array of strings, where each string
5967c478bd9Sstevel@tonic-gate * is a priority directory name. The end of the array is marked by a NULL
5977c478bd9Sstevel@tonic-gate * pointer. The priority directories' names are obtained from the file
5987c478bd9Sstevel@tonic-gate * /etc/ttysrch if it exists and is readable, or if not, a default hard-coded
5997c478bd9Sstevel@tonic-gate * list of directories.
6007c478bd9Sstevel@tonic-gate *
6017c478bd9Sstevel@tonic-gate * /etc/ttysrch, if used, is read in as a string of characters into memory and
6027c478bd9Sstevel@tonic-gate * then parsed into strings of priority directory names, omitting comments and
6037c478bd9Sstevel@tonic-gate * blank lines.
6047c478bd9Sstevel@tonic-gate *
6057c478bd9Sstevel@tonic-gate */
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate #define START_STATE 1
6087c478bd9Sstevel@tonic-gate #define COMMENT_STATE 2
6097c478bd9Sstevel@tonic-gate #define DIRNAME_STATE 3
6107c478bd9Sstevel@tonic-gate #define FLAG_STATE 4
6117c478bd9Sstevel@tonic-gate #define CHECK_STATE 5
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate #define COMMENT_CHAR '#'
6147c478bd9Sstevel@tonic-gate #define EOLN_CHAR '\n'
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate static const entry_t *
get_pri_dirs(void)6177c478bd9Sstevel@tonic-gate get_pri_dirs(void)
6187c478bd9Sstevel@tonic-gate {
6197c478bd9Sstevel@tonic-gate int fd, state;
6207c478bd9Sstevel@tonic-gate size_t sz;
6217c478bd9Sstevel@tonic-gate ssize_t size;
6227c478bd9Sstevel@tonic-gate struct stat64 sb;
6237c478bd9Sstevel@tonic-gate char *buf, *ebuf;
6247c478bd9Sstevel@tonic-gate entry_t *vec;
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate /*
6277c478bd9Sstevel@tonic-gate * if no /etc/ttysrch, use defaults
6287c478bd9Sstevel@tonic-gate */
6297c478bd9Sstevel@tonic-gate if ((fd = open(TTYSRCH, 0)) < 0)
6307c478bd9Sstevel@tonic-gate return (def_srch_dirs);
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate if (fstat64(fd, &sb) < 0) {
6337c478bd9Sstevel@tonic-gate (void) close(fd);
6347c478bd9Sstevel@tonic-gate return (def_srch_dirs);
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate sz = (size_t)sb.st_size;
6387c478bd9Sstevel@tonic-gate if (dir_vec != NULL && sz == dir_size &&
6397c478bd9Sstevel@tonic-gate sb.st_mtim.tv_sec == dir_mtim.tv_sec &&
6407c478bd9Sstevel@tonic-gate sb.st_mtim.tv_nsec == dir_mtim.tv_nsec) {
6417c478bd9Sstevel@tonic-gate /*
6427c478bd9Sstevel@tonic-gate * size & modification time match
6437c478bd9Sstevel@tonic-gate * no need to reread TTYSRCH
6447c478bd9Sstevel@tonic-gate * just return old pointer
6457c478bd9Sstevel@tonic-gate */
6467c478bd9Sstevel@tonic-gate (void) close(fd);
6477c478bd9Sstevel@tonic-gate return (dir_vec);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate buf = realloc(dir_buf, sz + 1);
6507c478bd9Sstevel@tonic-gate if (buf != NULL) {
6517c478bd9Sstevel@tonic-gate dir_buf = buf;
6527c478bd9Sstevel@tonic-gate size = read(fd, dir_buf, sz);
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate (void) close(fd);
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate if (buf == NULL || size < 0) {
6577c478bd9Sstevel@tonic-gate if (dir_vec != NULL) {
6587c478bd9Sstevel@tonic-gate free(dir_vec);
6597c478bd9Sstevel@tonic-gate dir_vec = NULL;
6607c478bd9Sstevel@tonic-gate }
6617c478bd9Sstevel@tonic-gate return ((entry_t *)def_srch_dirs);
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate dir_size = sz;
6647c478bd9Sstevel@tonic-gate dir_mtim = sb.st_mtim;
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate /*
6677c478bd9Sstevel@tonic-gate * ensure newline termination for buffer. Add an extra
6687c478bd9Sstevel@tonic-gate * entry to dir_vec for null terminator
6697c478bd9Sstevel@tonic-gate */
6707c478bd9Sstevel@tonic-gate ebuf = &dir_buf[size];
6717c478bd9Sstevel@tonic-gate *ebuf++ = '\n';
6727c478bd9Sstevel@tonic-gate for (sz = 1, buf = dir_buf; buf < ebuf; ++buf)
6737c478bd9Sstevel@tonic-gate if (*buf == '\n')
6747c478bd9Sstevel@tonic-gate ++sz;
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate sz *= sizeof (*dir_vec);
6777c478bd9Sstevel@tonic-gate vec = realloc(dir_vec, sz);
6787c478bd9Sstevel@tonic-gate if (vec == NULL) {
6797c478bd9Sstevel@tonic-gate if (dir_vec != NULL) {
6807c478bd9Sstevel@tonic-gate free(dir_vec);
6817c478bd9Sstevel@tonic-gate dir_vec = NULL;
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate return (def_srch_dirs);
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate dir_vec = vec;
6867c478bd9Sstevel@tonic-gate state = START_STATE;
6877c478bd9Sstevel@tonic-gate for (buf = dir_buf; buf < ebuf; ++buf) {
6887c478bd9Sstevel@tonic-gate switch (state) {
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate case START_STATE:
6917c478bd9Sstevel@tonic-gate if (*buf == COMMENT_CHAR) {
6927c478bd9Sstevel@tonic-gate state = COMMENT_STATE;
6937c478bd9Sstevel@tonic-gate break;
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate if (!isspace(*buf)) /* skip leading white space */
6967c478bd9Sstevel@tonic-gate state = DIRNAME_STATE;
6977c478bd9Sstevel@tonic-gate vec->name = buf;
6987c478bd9Sstevel@tonic-gate vec->flags = 0;
6997c478bd9Sstevel@tonic-gate break;
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate case COMMENT_STATE:
7027c478bd9Sstevel@tonic-gate if (*buf == EOLN_CHAR)
7037c478bd9Sstevel@tonic-gate state = START_STATE;
7047c478bd9Sstevel@tonic-gate break;
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate case DIRNAME_STATE:
7077c478bd9Sstevel@tonic-gate if (*buf == EOLN_CHAR) {
7087c478bd9Sstevel@tonic-gate state = CHECK_STATE;
7097c478bd9Sstevel@tonic-gate *buf = '\0';
7107c478bd9Sstevel@tonic-gate } else if (isspace(*buf)) {
7117c478bd9Sstevel@tonic-gate /* skip trailing white space */
7127c478bd9Sstevel@tonic-gate state = FLAG_STATE;
7137c478bd9Sstevel@tonic-gate *buf = '\0';
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate break;
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate case FLAG_STATE:
7187c478bd9Sstevel@tonic-gate switch (*buf) {
7197c478bd9Sstevel@tonic-gate case 'M':
7207c478bd9Sstevel@tonic-gate vec->flags |= MATCH_MM;
7217c478bd9Sstevel@tonic-gate break;
7227c478bd9Sstevel@tonic-gate case 'F':
7237c478bd9Sstevel@tonic-gate vec->flags |= MATCH_FS;
7247c478bd9Sstevel@tonic-gate break;
7257c478bd9Sstevel@tonic-gate case 'I':
7267c478bd9Sstevel@tonic-gate vec->flags |= MATCH_INO;
7277c478bd9Sstevel@tonic-gate break;
7287c478bd9Sstevel@tonic-gate case EOLN_CHAR:
7297c478bd9Sstevel@tonic-gate state = CHECK_STATE;
7307c478bd9Sstevel@tonic-gate break;
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate break;
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate case CHECK_STATE:
7357c478bd9Sstevel@tonic-gate if (strncmp(vec->name, DEV, strlen(DEV)) != 0) {
7367c478bd9Sstevel@tonic-gate int tfd = open("/dev/console", O_WRONLY);
7377c478bd9Sstevel@tonic-gate if (tfd >= 0) {
7387c478bd9Sstevel@tonic-gate char buf[256];
7397c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf),
7407c478bd9Sstevel@tonic-gate _libc_gettext(
74111a1a29eSlt200341 "ERROR: Entry '%s' in /etc/ttysrch ignored.\n"), vec->name);
7427c478bd9Sstevel@tonic-gate (void) write(tfd, buf, strlen(buf));
7437c478bd9Sstevel@tonic-gate (void) close(tfd);
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate } else {
7467c478bd9Sstevel@tonic-gate char *slash;
7477c478bd9Sstevel@tonic-gate slash = vec->name + strlen(vec->name) - 1;
7487c478bd9Sstevel@tonic-gate while (*slash == '/')
7497c478bd9Sstevel@tonic-gate *slash-- = '\0';
7507c478bd9Sstevel@tonic-gate if (vec->flags == 0)
7517c478bd9Sstevel@tonic-gate vec->flags = MATCH_ALL;
7527c478bd9Sstevel@tonic-gate vec++;
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate state = START_STATE;
7557c478bd9Sstevel@tonic-gate /*
7567c478bd9Sstevel@tonic-gate * This state does not consume a character, so
7577c478bd9Sstevel@tonic-gate * reposition the pointer.
7587c478bd9Sstevel@tonic-gate */
7597c478bd9Sstevel@tonic-gate buf--;
7607c478bd9Sstevel@tonic-gate break;
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate }
7647c478bd9Sstevel@tonic-gate vec->name = NULL;
7657c478bd9Sstevel@tonic-gate return (dir_vec);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate char *
ttyname(int f)7707c478bd9Sstevel@tonic-gate ttyname(int f)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate char *ans = tsdalloc(_T_TTYNAME, MAX_DEV_PATH, NULL);
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate if (ans == NULL)
7757c478bd9Sstevel@tonic-gate return (NULL);
7767257d1b4Sraf return (ttyname_r(f, ans, MAX_DEV_PATH));
7777c478bd9Sstevel@tonic-gate }
778