xref: /onnv-gate/usr/src/cmd/csh/sh.tchar.c (revision 2182:221c5b409327)
10Sstevel@tonic-gate /*
2*2182Schin  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
70Sstevel@tonic-gate /*	  All Rights Reserved  	*/
80Sstevel@tonic-gate 
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
110Sstevel@tonic-gate  * All rights reserved. The Berkeley Software License Agreement
120Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
130Sstevel@tonic-gate  */
140Sstevel@tonic-gate 
150Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
160Sstevel@tonic-gate 
170Sstevel@tonic-gate /*
180Sstevel@tonic-gate  * This module provides with system/library function substitutes for tchar
190Sstevel@tonic-gate  * datatype. This also includes two conversion functions between tchar and
200Sstevel@tonic-gate  * char arrays.
210Sstevel@tonic-gate  *
220Sstevel@tonic-gate  * T. Kurosaka, Palo Alto, California, USA
230Sstevel@tonic-gate  * March 1989
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * Implementation Notes:
260Sstevel@tonic-gate  *	Many functions defined here use a "char" buffer chbuf[].  In the
270Sstevel@tonic-gate  * first attempt, there used to be only one chbuf defined as static
280Sstevel@tonic-gate  * (private) variable and shared by these functions.  csh linked with that
290Sstevel@tonic-gate  * version of this file misbehaved in interpreting "eval `tset ....`".
300Sstevel@tonic-gate  * (in general, builtin function with back-quoted expression).
310Sstevel@tonic-gate  *	This bug seemed to be caused by sharing of chbuf
320Sstevel@tonic-gate  * by these functions simultanously (thru vfork() mechanism?).  We could not
330Sstevel@tonic-gate  * identify which two functions interfere each other so we decided to
340Sstevel@tonic-gate  * have each of these function its private instance of chbuf.
350Sstevel@tonic-gate  * The size of chbuf[] might be much bigger than necessary for some functions.
360Sstevel@tonic-gate  */
370Sstevel@tonic-gate #ifdef DBG
380Sstevel@tonic-gate #include <stdio.h>	/* For <assert.h> needs stderr defined. */
390Sstevel@tonic-gate #else /* !DBG */
400Sstevel@tonic-gate #define	NDEBUG		/* Disable assert(). */
410Sstevel@tonic-gate #endif /* !DBG */
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #include <assert.h>
440Sstevel@tonic-gate #include "sh.h"
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #ifdef MBCHAR
470Sstevel@tonic-gate #include <widec.h>	/* For wcsetno() */
480Sstevel@tonic-gate #endif
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #include <sys/param.h>	/* MAXPATHLEN */
510Sstevel@tonic-gate #include <fcntl.h>
520Sstevel@tonic-gate #include <unistd.h>
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate  * strtots(to, from): convert a char string 'from' into a tchar buffer 'to'.
570Sstevel@tonic-gate  *	'to' is assumed to have the enough size to hold the conversion result.
580Sstevel@tonic-gate  *	When 'to' is NOSTR(=(tchar *)0), strtots() attempts to allocate a space
590Sstevel@tonic-gate  *	automatically using xalloc().  It is caller's responsibility to
60559Snakanon  *	free the space allocated in this way, by calling xfree(ptr).
610Sstevel@tonic-gate  *	In either case, strtots() returns the pointer to the conversion
620Sstevel@tonic-gate  *	result (i.e. 'to', if 'to' wasn't NOSTR, or the allocated space.).
630Sstevel@tonic-gate  *	When a conversion or allocateion failed,  NOSTR is returned.
640Sstevel@tonic-gate  */
650Sstevel@tonic-gate 
660Sstevel@tonic-gate tchar	*
strtots(tchar * to,char * from)670Sstevel@tonic-gate strtots(tchar *to, char *from)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	int	i;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	if (to == NOSTR) {	/* Need to xalloc(). */
720Sstevel@tonic-gate 		int	i;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 		i = mbstotcs(NOSTR, from, 0);
750Sstevel@tonic-gate 		if (i < 0) {
760Sstevel@tonic-gate 			return (NOSTR);
770Sstevel@tonic-gate 		}
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 		/* Allocate space for the resulting tchar array. */
800Sstevel@tonic-gate 		to = (tchar *)xalloc(i * sizeof (tchar));
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 	i = mbstotcs(to, from, INT_MAX);
830Sstevel@tonic-gate 	if (i < 0) {
840Sstevel@tonic-gate 		return (NOSTR);
850Sstevel@tonic-gate 	}
860Sstevel@tonic-gate 	return (to);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate char	*
tstostr(char * to,tchar * from)900Sstevel@tonic-gate tstostr(char *to, tchar *from)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate 	tchar	*ptc;
930Sstevel@tonic-gate 	wchar_t	wc;
940Sstevel@tonic-gate 	char	*pmb;
950Sstevel@tonic-gate 	int	len;
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	if (to == (char *)NULL) {	/* Need to xalloc(). */
980Sstevel@tonic-gate 		int	i;
990Sstevel@tonic-gate 		int	i1;
1000Sstevel@tonic-gate 		char	junk[MB_LEN_MAX];
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 		/* Get sum of byte counts for each char in from. */
1030Sstevel@tonic-gate 		i = 0;
1040Sstevel@tonic-gate 		ptc = from;
1050Sstevel@tonic-gate 		while (wc = (wchar_t)((*ptc++)&TRIM)) {
1060Sstevel@tonic-gate 			if ((i1 = wctomb(junk, wc)) <= 0) {
1070Sstevel@tonic-gate 				i1 = 1;
1080Sstevel@tonic-gate 			}
1090Sstevel@tonic-gate 			i += i1;
1100Sstevel@tonic-gate 		}
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 		/* Allocate that much. */
1130Sstevel@tonic-gate 		to = (char *)xalloc(i + 1);
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	ptc = from;
1170Sstevel@tonic-gate 	pmb = to;
1180Sstevel@tonic-gate 	while (wc = (wchar_t)((*ptc++)&TRIM)) {
1190Sstevel@tonic-gate 		if ((len = wctomb(pmb, wc)) <= 0) {
1200Sstevel@tonic-gate 			*pmb = (unsigned char)wc;
1210Sstevel@tonic-gate 			len = 1;
1220Sstevel@tonic-gate 		}
1230Sstevel@tonic-gate 		pmb += len;
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 	*pmb = (char)0;
1260Sstevel@tonic-gate 	return (to);
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate /*
1300Sstevel@tonic-gate  * mbstotcs(to, from, tosize) is similar to strtots() except that
1310Sstevel@tonic-gate  * this returns # of tchars of the resulting tchar string.
1320Sstevel@tonic-gate  * When NULL is give as the destination, no real conversion is carried out,
1330Sstevel@tonic-gate  * and the function reports how many tchar characters would be made in
1340Sstevel@tonic-gate  * the converted result including the terminating 0.
1350Sstevel@tonic-gate  *	tchar	*to;	- Destination buffer, or NULL.
1360Sstevel@tonic-gate  *	char	*from;	- Source string.
1370Sstevel@tonic-gate  *	int	tosize; - Size of to, in terms of # of tchars.
1380Sstevel@tonic-gate  */
1390Sstevel@tonic-gate int
mbstotcs(tchar * to,char * from,int tosize)1400Sstevel@tonic-gate mbstotcs(tchar *to, char *from, int tosize)
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate 	tchar	*ptc = to;
1430Sstevel@tonic-gate 	char	*pmb = from;
1440Sstevel@tonic-gate 	wchar_t	wc;
1450Sstevel@tonic-gate 	int	chcnt = 0;
1460Sstevel@tonic-gate 	int	j;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/* Just count how many tchar would be in the result. */
1500Sstevel@tonic-gate 	if (to == (tchar *)NULL) {
1510Sstevel@tonic-gate 		while (*pmb) {
1520Sstevel@tonic-gate 			if ((j = mbtowc(&wc, pmb, MB_CUR_MAX)) <= 0) {
1530Sstevel@tonic-gate 				j = 1;
1540Sstevel@tonic-gate 			}
1550Sstevel@tonic-gate 			pmb += j;
1560Sstevel@tonic-gate 			chcnt++;
1570Sstevel@tonic-gate 		}
1580Sstevel@tonic-gate 		chcnt++;	/* For terminator. */
1590Sstevel@tonic-gate 		return (chcnt);	/* # of chars including terminating zero. */
1600Sstevel@tonic-gate 	} else {	/* Do the real conversion. */
1610Sstevel@tonic-gate 		while (*pmb) {
1620Sstevel@tonic-gate 			if ((j = mbtowc(&wc, pmb, MB_CUR_MAX)) <= 0) {
1630Sstevel@tonic-gate 				wc = (unsigned char)*pmb;
1640Sstevel@tonic-gate 				j = 1;
1650Sstevel@tonic-gate 			}
1660Sstevel@tonic-gate 			pmb += j;
1670Sstevel@tonic-gate 			*(ptc++) = (tchar)wc;
1680Sstevel@tonic-gate 			if (++chcnt >= tosize) {
1690Sstevel@tonic-gate 				break;
1700Sstevel@tonic-gate 			}
1710Sstevel@tonic-gate 		}
1720Sstevel@tonic-gate 		/* Terminate with zero only when space is left. */
1730Sstevel@tonic-gate 		if (chcnt < tosize) {
1740Sstevel@tonic-gate 			*ptc = (tchar)0;
1750Sstevel@tonic-gate 			++chcnt;
1760Sstevel@tonic-gate 		}
1770Sstevel@tonic-gate 		return (chcnt); /* # of chars including terminating zero. */
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate /* tchar version of STRING functions. */
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate  * Returns the number of
1860Sstevel@tonic-gate  * non-NULL tchar elements in tchar string argument.
1870Sstevel@tonic-gate  */
1880Sstevel@tonic-gate int
strlen_(tchar * s)1890Sstevel@tonic-gate strlen_(tchar *s)
1900Sstevel@tonic-gate {
1910Sstevel@tonic-gate 	int n;
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	n = 0;
1940Sstevel@tonic-gate 	while (*s++) {
1950Sstevel@tonic-gate 		n++;
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 	return (n);
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate /*
2010Sstevel@tonic-gate  * Concatenate tchar string s2 on the end of s1.  S1's space must be large
2020Sstevel@tonic-gate  * enough.  Return s1.
2030Sstevel@tonic-gate  */
2040Sstevel@tonic-gate tchar *
strcat_(tchar * s1,tchar * s2)2050Sstevel@tonic-gate strcat_(tchar *s1, tchar *s2)
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate 	tchar *os1;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	os1 = s1;
2100Sstevel@tonic-gate 	while (*s1++)
2110Sstevel@tonic-gate 		;
2120Sstevel@tonic-gate 	--s1;
2130Sstevel@tonic-gate 	while (*s1++ = *s2++)
2140Sstevel@tonic-gate 		;
2150Sstevel@tonic-gate 	return (os1);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate /*
2190Sstevel@tonic-gate  * Compare tchar strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
2200Sstevel@tonic-gate  * BUGS: Comparison between two characters are done by subtracting two chars
2210Sstevel@tonic-gate  *	after converting each to an unsigned long int value.  It might not make
2220Sstevel@tonic-gate  *	a whole lot of sense to do that if the characters are in represented
2230Sstevel@tonic-gate  *	as wide characters and the two characters belong to different codesets.
2240Sstevel@tonic-gate  *	Therefore, this function should be used only to test the equallness.
2250Sstevel@tonic-gate  */
2260Sstevel@tonic-gate int
strcmp_(tchar * s1,tchar * s2)2270Sstevel@tonic-gate strcmp_(tchar *s1, tchar *s2)
2280Sstevel@tonic-gate {
2290Sstevel@tonic-gate 	while (*s1 == *s2++) {
2300Sstevel@tonic-gate 		if (*s1++ == (tchar)0) {
2310Sstevel@tonic-gate 			return (0);
2320Sstevel@tonic-gate 		}
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 	return (((unsigned long)*s1) - ((unsigned long)*(--s2)));
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  * This is only used in sh.glob.c for sorting purpose.
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate int
strcoll_(tchar * s1,tchar * s2)2410Sstevel@tonic-gate strcoll_(tchar *s1, tchar *s2)
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate 	char buf1[BUFSIZ];
2440Sstevel@tonic-gate 	char buf2[BUFSIZ];
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	tstostr(buf1, s1);
2470Sstevel@tonic-gate 	tstostr(buf2, s2);
2480Sstevel@tonic-gate 	return (strcoll(buf1, buf2));
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate  * Copy tchar string s2 to s1.  s1 must be large enough.
2530Sstevel@tonic-gate  * return s1
2540Sstevel@tonic-gate  */
2550Sstevel@tonic-gate tchar *
strcpy_(tchar * s1,tchar * s2)2560Sstevel@tonic-gate strcpy_(tchar *s1, tchar *s2)
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate 	tchar *os1;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	os1 = s1;
2610Sstevel@tonic-gate 	while (*s1++ = *s2++)
2620Sstevel@tonic-gate 		;
2630Sstevel@tonic-gate 	return (os1);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate /*
2670Sstevel@tonic-gate  * Return the ptr in sp at which the character c appears;
2680Sstevel@tonic-gate  * NULL if not found
2690Sstevel@tonic-gate  */
2700Sstevel@tonic-gate tchar *
index_(tchar * sp,tchar c)2710Sstevel@tonic-gate index_(tchar *sp, tchar c)
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	do {
2750Sstevel@tonic-gate 		if (*sp == c) {
2760Sstevel@tonic-gate 			return (sp);
2770Sstevel@tonic-gate 		}
2780Sstevel@tonic-gate 	} while (*sp++);
2790Sstevel@tonic-gate 	return (NULL);
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate /*
2830Sstevel@tonic-gate  * Return the ptr in sp at which the character c last
2840Sstevel@tonic-gate  * appears; NOSTR if not found
2850Sstevel@tonic-gate  */
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate tchar *
rindex_(tchar * sp,tchar c)2880Sstevel@tonic-gate rindex_(tchar *sp, tchar c)
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate 	tchar *r;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	r = NOSTR;
2930Sstevel@tonic-gate 	do {
2940Sstevel@tonic-gate 		if (*sp == c) {
2950Sstevel@tonic-gate 			r = sp;
2960Sstevel@tonic-gate 		}
2970Sstevel@tonic-gate 	} while (*sp++);
2980Sstevel@tonic-gate 	return (r);
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate /* Additional misc functions. */
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate /* Calculate the display width of a string.  */
304356Smuffin int
tswidth(tchar * ts)3050Sstevel@tonic-gate tswidth(tchar *ts)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate #ifdef MBCHAR
3080Sstevel@tonic-gate 	wchar_t	tc;
3090Sstevel@tonic-gate 	int	w = 0;
3100Sstevel@tonic-gate 	int	p_col;
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	while (tc = *ts++) {
3130Sstevel@tonic-gate 		if ((p_col = wcwidth((wchar_t)tc)) > 0)
3140Sstevel@tonic-gate 			w += p_col;
3150Sstevel@tonic-gate 	}
3160Sstevel@tonic-gate 	return (w);
3170Sstevel@tonic-gate #else /* !MBCHAR --- one char always occupies one column. */
3180Sstevel@tonic-gate 	return (strlen_(ts));
3190Sstevel@tonic-gate #endif
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate  * Two getenv() substitute functions.  They differ in the type of arguments.
3240Sstevel@tonic-gate  * BUGS: Both returns the pointer to an allocated space where the env var's
3250Sstevel@tonic-gate  *	values is stored.  This space is freed automatically on the successive
3260Sstevel@tonic-gate  *	call of	either function.  Therefore the caller must copy the contents
3270Sstevel@tonic-gate  *	if it needs to access two env vars.  There is an arbitary limitation
3280Sstevel@tonic-gate  *	on the number of chars of a env var name.
3290Sstevel@tonic-gate  */
3300Sstevel@tonic-gate #define	LONGEST_ENVVARNAME	256		/* Too big? */
3310Sstevel@tonic-gate tchar *
getenv_(tchar * name_)3320Sstevel@tonic-gate getenv_(tchar *name_)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate 	char	name[LONGEST_ENVVARNAME * MB_LEN_MAX];
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	assert(strlen_(name_) < LONGEST_ENVVARNAME);
3370Sstevel@tonic-gate 	return (getenvs_(tstostr(name, name_)));
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate tchar *
getenvs_(char * name)3410Sstevel@tonic-gate getenvs_(char *name)
3420Sstevel@tonic-gate {
3430Sstevel@tonic-gate 	static tchar	*pbuf = (tchar *)NULL;
3440Sstevel@tonic-gate 	char	*val;
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	if (pbuf) {
347559Snakanon 		xfree(pbuf);
3480Sstevel@tonic-gate 		pbuf = NOSTR;
3490Sstevel@tonic-gate 	}
3500Sstevel@tonic-gate 	val = getenv(name);
3510Sstevel@tonic-gate 	if (val == (char *)NULL) {
3520Sstevel@tonic-gate 		return (NOSTR);
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 	return (pbuf = strtots(NOSTR, val));
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate /* Followings are the system call interface for tchar strings. */
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate /*
3600Sstevel@tonic-gate  * creat() and open() replacement.
3610Sstevel@tonic-gate  * BUGS: An unusually long file name could be dangerous.
3620Sstevel@tonic-gate  */
3630Sstevel@tonic-gate int
creat_(tchar * name_,int mode)3640Sstevel@tonic-gate creat_(tchar *name_, int mode)
3650Sstevel@tonic-gate {
3660Sstevel@tonic-gate 	int fd;
3670Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	tstostr(chbuf, name_);
3700Sstevel@tonic-gate 	fd = creat((char *)chbuf, mode);
3710Sstevel@tonic-gate 	if (fd != -1) {
3720Sstevel@tonic-gate 		setfd(fd);
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 	return (fd);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate /*VARARGS2*/
3780Sstevel@tonic-gate int
open_(path_,flags,mode)3790Sstevel@tonic-gate open_(path_, flags, mode)
3800Sstevel@tonic-gate 	tchar 	*path_;
3810Sstevel@tonic-gate 	int	flags;
3820Sstevel@tonic-gate 	int	mode; /* May be omitted. */
3830Sstevel@tonic-gate {
3840Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
3850Sstevel@tonic-gate 	int fd;
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	tstostr(chbuf, path_);
3880Sstevel@tonic-gate 	fd = open((char *)chbuf, flags, mode);
3890Sstevel@tonic-gate 	if (fd != -1) {
3900Sstevel@tonic-gate 		setfd(fd);
3910Sstevel@tonic-gate 	}
3920Sstevel@tonic-gate 	return (fd);
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate /*
3960Sstevel@tonic-gate  * mkstemp replacement
3970Sstevel@tonic-gate  */
3980Sstevel@tonic-gate int
mkstemp_(tchar * name_)3990Sstevel@tonic-gate mkstemp_(tchar *name_)
4000Sstevel@tonic-gate {
4010Sstevel@tonic-gate 	int fd;
4020Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	tstostr(chbuf, name_);
4050Sstevel@tonic-gate 	fd = mkstemp((char *)chbuf);
4060Sstevel@tonic-gate 	if (fd != -1) {
4070Sstevel@tonic-gate 		setfd(fd);
4080Sstevel@tonic-gate 		strtots(name_, chbuf);
4090Sstevel@tonic-gate 	}
4100Sstevel@tonic-gate 	return (fd);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate  * read() and write() reaplacement.
4150Sstevel@tonic-gate  *	int        d;
4160Sstevel@tonic-gate  *	tchar      *buf;  - where the result be stored.  Not NULL terminated.
4170Sstevel@tonic-gate  *	int        nchreq; - # of tchars requrested.
4180Sstevel@tonic-gate  */
4190Sstevel@tonic-gate int
read_(int d,tchar * buf,int nchreq)4200Sstevel@tonic-gate read_(int d, tchar *buf, int nchreq)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 	unsigned char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
4230Sstevel@tonic-gate #ifdef MBCHAR
4240Sstevel@tonic-gate 	/*
4250Sstevel@tonic-gate 	 * We would have to read more than tchar bytes
4260Sstevel@tonic-gate 	 * when there are multibyte characters in the file.
4270Sstevel@tonic-gate 	 */
4280Sstevel@tonic-gate 	int	i, j, fflags;
4290Sstevel@tonic-gate 	unsigned char	*s;	/* Byte being scanned for a multibyte char. */
4300Sstevel@tonic-gate 	/* Points to the pos where next read() to read the data into. */
4310Sstevel@tonic-gate 	unsigned char	*p;
4320Sstevel@tonic-gate 	tchar	*t;
4330Sstevel@tonic-gate 	wchar_t		wc;
4340Sstevel@tonic-gate 	int		b_len;
4350Sstevel@tonic-gate 	int		nchread = 0; /* Count how many bytes has been read. */
4360Sstevel@tonic-gate 	int		nbytread = 0; /* Total # of bytes read. */
4370Sstevel@tonic-gate 	/* # of bytes needed to complete the last char just read. */
4380Sstevel@tonic-gate 	int		delta;
4390Sstevel@tonic-gate 	unsigned char	*q;	/* q points to the first invalid byte. */
440559Snakanon 	int		mb_cur_max = MB_CUR_MAX;
4410Sstevel@tonic-gate #ifdef DBG
4420Sstevel@tonic-gate 	tprintf("Entering read_(d=%d, buf=0x%x, nchreq=%d);\n",
4430Sstevel@tonic-gate 	    d, buf, nchreq);
4440Sstevel@tonic-gate #endif /* DBG */
4450Sstevel@tonic-gate 	/*
4460Sstevel@tonic-gate 	 *	Step 1: We collect the exact number of bytes that make
4470Sstevel@tonic-gate 	 *	nchreq characters into chbuf.
4480Sstevel@tonic-gate 	 *	We must be careful not to read too many bytes as we
4490Sstevel@tonic-gate 	 *	cannot push back such over-read bytes.
4500Sstevel@tonic-gate 	 *	The idea we use here is that n multibyte characters are stored
4510Sstevel@tonic-gate 	 *	in no less than n but less than n*MB_CUR_MAX bytes.
4520Sstevel@tonic-gate 	 */
4530Sstevel@tonic-gate 	assert(nchreq <= BUFSIZ);
4540Sstevel@tonic-gate 	delta = 0;
4550Sstevel@tonic-gate 	p = s = chbuf;
4560Sstevel@tonic-gate 	t = buf;
4570Sstevel@tonic-gate 	while (nchread < nchreq) {
4580Sstevel@tonic-gate 		int		m;  /* # of bytes to try to read this time. */
4590Sstevel@tonic-gate 		int		k;  /* # of bytes successfully read. */
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate retry:
4620Sstevel@tonic-gate 		/*
4630Sstevel@tonic-gate 		 * Let's say the (N+1)'th byte bN is actually the first
4640Sstevel@tonic-gate 		 * byte of a three-byte character c.
4650Sstevel@tonic-gate 		 * In that case, p, s, q look like this:
4660Sstevel@tonic-gate 		 *
4670Sstevel@tonic-gate 		 *		/-- already read--\ /-- not yet read --\
4680Sstevel@tonic-gate 		 * chbuf[]:	b0 b1 ..... bN bN+1 bN+2 bN+2 ...
4690Sstevel@tonic-gate 		 *		^		^	^
4700Sstevel@tonic-gate 		 *		|		|	|
4710Sstevel@tonic-gate 		 *		p		s	q
4720Sstevel@tonic-gate 		 *				\----------/
4730Sstevel@tonic-gate 		 *				c hasn't been completed
4740Sstevel@tonic-gate 		 *
4750Sstevel@tonic-gate 		 * Just after the next read(), p and q will be adavanced to:
4760Sstevel@tonic-gate 		 *
4770Sstevel@tonic-gate 		 *	/-- already read-----------------------\ /-- not yet -
4780Sstevel@tonic-gate 		 * chbuf[]: b0 b1 ..... bN bN+1 bN+2 bN+2 ... bX bX+1 bX+2...
4790Sstevel@tonic-gate 		 *			^	^		 ^
4800Sstevel@tonic-gate 		 *			|	|		 |
4810Sstevel@tonic-gate 		 *			s	p		 q
4820Sstevel@tonic-gate 		 *			\----------/
4830Sstevel@tonic-gate 		 *			 c has been completed
4840Sstevel@tonic-gate 		 *			 but hasn't been scanned
4850Sstevel@tonic-gate 		 */
4860Sstevel@tonic-gate 		m = nchreq - nchread;
4870Sstevel@tonic-gate 		assert(p + m < chbuf + sizeof (chbuf));
4880Sstevel@tonic-gate 		k = read(d, p, m);
4890Sstevel@tonic-gate 		/*
4900Sstevel@tonic-gate 		 * when child sets O_NDELAY or O_NONBLOCK on stdin
4910Sstevel@tonic-gate 		 * and exits and we are interactive then turn the modes off
4920Sstevel@tonic-gate 		 * and retry
4930Sstevel@tonic-gate 		 */
4940Sstevel@tonic-gate 		if (k == 0) {
4950Sstevel@tonic-gate 			if ((intty && !onelflg && !cflg) &&
4960Sstevel@tonic-gate 			    ((fflags = fcntl(d, F_GETFL, 0)) & O_NDELAY)) {
4970Sstevel@tonic-gate 				fflags &= ~O_NDELAY;
4980Sstevel@tonic-gate 				fcntl(d, F_SETFL, fflags);
4990Sstevel@tonic-gate 				goto retry;
5000Sstevel@tonic-gate 			}
5010Sstevel@tonic-gate 		} else if (k < 0) {
5020Sstevel@tonic-gate 			if (errno == EAGAIN) {
5030Sstevel@tonic-gate 				fflags = fcntl(d, F_GETFL, 0);
5040Sstevel@tonic-gate 				fflags &= ~O_NONBLOCK;
5050Sstevel@tonic-gate 				fcntl(d, F_SETFL, fflags);
5060Sstevel@tonic-gate 				goto retry;
5070Sstevel@tonic-gate 			}
5080Sstevel@tonic-gate 			return (-1);
5090Sstevel@tonic-gate 		}
5100Sstevel@tonic-gate 		nbytread += k;
5110Sstevel@tonic-gate 		q = p + k;
5120Sstevel@tonic-gate 		delta = 0;
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 		/* Try scaning characters in s..q-1 */
5150Sstevel@tonic-gate 		while (s < q) {
5160Sstevel@tonic-gate 			/* Convert the collected bytes into tchar array. */
5170Sstevel@tonic-gate 			if (*s == 0) {
5180Sstevel@tonic-gate 				/* NUL is treated as a normal char here. */
5190Sstevel@tonic-gate 				*t++ = 0;
5200Sstevel@tonic-gate 				s++;
5210Sstevel@tonic-gate 				nchread++;
5220Sstevel@tonic-gate 				continue;
5230Sstevel@tonic-gate 			}
5240Sstevel@tonic-gate 
525559Snakanon 			if ((b_len = q - s) > mb_cur_max) {
526559Snakanon 				b_len = mb_cur_max;
5270Sstevel@tonic-gate 			}
5280Sstevel@tonic-gate 			if ((j = mbtowc(&wc, (char *)s, b_len)) <=  0) {
529559Snakanon 				if (mb_cur_max > 1 && b_len < mb_cur_max) {
5300Sstevel@tonic-gate 					/*
5310Sstevel@tonic-gate 					 * Needs more byte to complete this char
5320Sstevel@tonic-gate 					 * In order to read() more than delta
5330Sstevel@tonic-gate 					 * bytes.
5340Sstevel@tonic-gate 					 */
5350Sstevel@tonic-gate 					break;
5360Sstevel@tonic-gate 				}
5370Sstevel@tonic-gate 				wc = (unsigned char)*s;
5380Sstevel@tonic-gate 				j = 1;
5390Sstevel@tonic-gate 			}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 			*t++ = wc;
5420Sstevel@tonic-gate 			nchread++;
5430Sstevel@tonic-gate 			s += j;
5440Sstevel@tonic-gate 		}
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 		if (k < m) {
5470Sstevel@tonic-gate 			/* We've read as many bytes as possible. */
5480Sstevel@tonic-gate 			while (s < q) {
549559Snakanon 				if ((b_len = q - s) > mb_cur_max) {
550559Snakanon 					b_len = mb_cur_max;
5510Sstevel@tonic-gate 				}
5520Sstevel@tonic-gate 				if ((j = mbtowc(&wc, (char *)s, b_len)) <=  0) {
5530Sstevel@tonic-gate 					wc = (unsigned char)*s;
5540Sstevel@tonic-gate 					j = 1;
5550Sstevel@tonic-gate 				}
5560Sstevel@tonic-gate 				*t++ = wc;
5570Sstevel@tonic-gate 				nchread++;
5580Sstevel@tonic-gate 				s += j;
5590Sstevel@tonic-gate 			}
5600Sstevel@tonic-gate 			return (nchread);
5610Sstevel@tonic-gate 		}
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 		p = q;
5640Sstevel@tonic-gate 	}
5650Sstevel@tonic-gate 
566559Snakanon 	if (mb_cur_max == 1 || (delta = q - s) == 0) {
5670Sstevel@tonic-gate 		return (nchread);
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate 
570559Snakanon 	/*
571559Snakanon 	 * We may have (MB_CUR_MAX - 1) unread data in the buffer.
572559Snakanon 	 * Here, the last converted data was an illegal character which was
573559Snakanon 	 * treated as one byte character. We don't know at this point
574559Snakanon 	 * whether or not the remaining data is in legal sequence.
575559Snakanon 	 * We first attempt to convert the remaining data.
576559Snakanon 	 */
577559Snakanon 	do {
578559Snakanon 		if ((j = mbtowc(&wc, (char *)s, delta)) <= 0)
579559Snakanon 			break;
580559Snakanon 		*t++ = wc;
581559Snakanon 		nchread++;
582559Snakanon 		s += j;
583559Snakanon 		delta -= j;
584559Snakanon 	} while (delta > 0);
585559Snakanon 
586559Snakanon 	if (delta == 0)
5870Sstevel@tonic-gate 		return (nchread);
5880Sstevel@tonic-gate 
589559Snakanon 	/*
590559Snakanon 	 * There seem to be ugly sequence in the buffer. Fill up till
591559Snakanon 	 * mb_cur_max and see if we can get a right sequence.
592559Snakanon 	 */
593559Snakanon 	while (delta < mb_cur_max) {
5940Sstevel@tonic-gate 		assert((q + 1) < (chbuf + sizeof (chbuf)));
595559Snakanon 		if (read(d, q, 1) != 1)
5960Sstevel@tonic-gate 			break;
597559Snakanon 		delta++;
598559Snakanon 		q++;
5990Sstevel@tonic-gate 		if (mbtowc(&wc, (char *)s, delta) > 0) {
6000Sstevel@tonic-gate 			*t = wc;
6010Sstevel@tonic-gate 			return (nchread + 1);
6020Sstevel@tonic-gate 		}
6030Sstevel@tonic-gate 	}
6040Sstevel@tonic-gate 
605559Snakanon 	/*
606559Snakanon 	 * no luck. we have filled MB_CUR_MAX bytes in the buffer.
607559Snakanon 	 * Ideally we should return with leaving such data off and
608559Snakanon 	 * put them into a local buffer for next read, but we don't
609559Snakanon 	 * have such.
610559Snakanon 	 * So, stop reading further, and treat them as all single
611559Snakanon 	 * byte characters.
612559Snakanon 	 */
6130Sstevel@tonic-gate 	while (s < q) {
614559Snakanon 		b_len = q - s;
6150Sstevel@tonic-gate 		if ((j = mbtowc(&wc, (char *)s, b_len)) <=  0) {
6160Sstevel@tonic-gate 			wc = (unsigned char)*s;
6170Sstevel@tonic-gate 			j = 1;
6180Sstevel@tonic-gate 		}
6190Sstevel@tonic-gate 		*t++ = wc;
6200Sstevel@tonic-gate 		nchread++;
6210Sstevel@tonic-gate 		s += j;
6220Sstevel@tonic-gate 	}
6230Sstevel@tonic-gate 	return (nchread);
624559Snakanon 
6250Sstevel@tonic-gate #else /* !MBCHAR */
6260Sstevel@tonic-gate 	/* One byte always represents one tchar.  Easy! */
6270Sstevel@tonic-gate 	int		i;
6280Sstevel@tonic-gate 	unsigned char	*s;
6290Sstevel@tonic-gate 	tchar		*t;
6300Sstevel@tonic-gate 	int		nchread;
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate #ifdef DBG
6330Sstevel@tonic-gate 	tprintf("Entering read_(d=%d, buf=0x%x, nchreq=%d);\n",
6340Sstevel@tonic-gate 	    d, buf, nchreq);
6350Sstevel@tonic-gate #endif /* DBG */
6360Sstevel@tonic-gate 	assert(nchreq <= BUFSIZ);
6370Sstevel@tonic-gate retry:
6380Sstevel@tonic-gate 	nchread = read(d, (char *)chbuf, nchreq);
6390Sstevel@tonic-gate 	/*
6400Sstevel@tonic-gate 	 * when child sets O_NDELAY or O_NONBLOCK on stdin
6410Sstevel@tonic-gate 	 * and exits and we are interactive then turn the modes off
6420Sstevel@tonic-gate 	 * and retry
6430Sstevel@tonic-gate 	 */
6440Sstevel@tonic-gate 	if (nchread == 0) {
6450Sstevel@tonic-gate 		if ((intty && !onelflg && !cflg) &&
6460Sstevel@tonic-gate 		    ((fflags = fcntl(d, F_GETFL, 0)) & O_NDELAY)) {
6470Sstevel@tonic-gate 			fflags &= ~O_NDELAY;
6480Sstevel@tonic-gate 			fcntl(d, F_SETFL, fflags);
6490Sstevel@tonic-gate 			goto retry;
6500Sstevel@tonic-gate 		}
6510Sstevel@tonic-gate 	} else if (nchread < 0) {
6520Sstevel@tonic-gate 		if (errno == EAGAIN) {
6530Sstevel@tonic-gate 			fflags = fcntl(d, F_GETFL, 0);
6540Sstevel@tonic-gate 			fflags &= ~O_NONBLOCK;
6550Sstevel@tonic-gate 			fcntl(d, F_SETFL, fflags);
6560Sstevel@tonic-gate 			goto retry;
6570Sstevel@tonic-gate 		}
6580Sstevel@tonic-gate 		len = 0;
6590Sstevel@tonic-gate 	} else {
6600Sstevel@tonic-gate 		for (i = 0, t = buf, s = chbuf; i < nchread; ++i) {
6610Sstevel@tonic-gate 		    *t++ = ((tchar)*s++);
6620Sstevel@tonic-gate 		}
6630Sstevel@tonic-gate 	}
6640Sstevel@tonic-gate 	return (nchread);
6650Sstevel@tonic-gate #endif
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate /*
6690Sstevel@tonic-gate  * BUG: write_() returns -1 on failure, or # of BYTEs it has written.
6700Sstevel@tonic-gate  *	For consistency and symmetry, it should return the number of
6710Sstevel@tonic-gate  *	characters it has actually written, but that is technically
6720Sstevel@tonic-gate  *	difficult although not impossible.  Anyway, the return
6730Sstevel@tonic-gate  *	value of write() has never been used by the original csh,
6740Sstevel@tonic-gate  *	so this bug should be OK.
6750Sstevel@tonic-gate  */
6760Sstevel@tonic-gate int
write_(int d,tchar * buf,int nch)6770Sstevel@tonic-gate write_(int d, tchar *buf, int nch)
6780Sstevel@tonic-gate {
6790Sstevel@tonic-gate 	unsigned char chbuf[BUFSIZ*MB_LEN_MAX]; /* General use buffer. */
6800Sstevel@tonic-gate #ifdef MBCHAR
6810Sstevel@tonic-gate 	tchar		*pt;
6820Sstevel@tonic-gate 	unsigned char	*pc;
6830Sstevel@tonic-gate 	wchar_t		wc;
6840Sstevel@tonic-gate 	int		i, j;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate #ifdef	DBG
6870Sstevel@tonic-gate 	tprintf("Entering write_(d=%d, buf=0x%x, nch=%d);\n",
6880Sstevel@tonic-gate 	    d, buf, nch); /* Hope printf() doesn't call write_() itself! */
6890Sstevel@tonic-gate #endif /* DBG */
6900Sstevel@tonic-gate 	assert(nch * MB_CUR_MAX < sizeof (chbuf));
6910Sstevel@tonic-gate 	i = nch;
6920Sstevel@tonic-gate 	pt = buf;
6930Sstevel@tonic-gate 	pc = chbuf;
6940Sstevel@tonic-gate 	while (i--) {
6950Sstevel@tonic-gate 		/*
6960Sstevel@tonic-gate 		 * Convert to tchar string.
6970Sstevel@tonic-gate 		 * NUL is treated as normal char here.
6980Sstevel@tonic-gate 		 */
6990Sstevel@tonic-gate 		wc = (wchar_t)((*pt++)&TRIM);
7000Sstevel@tonic-gate 		if (wc == (wchar_t)0) {
7010Sstevel@tonic-gate 			*pc++ = 0;
7020Sstevel@tonic-gate 		} else {
7030Sstevel@tonic-gate 			if ((j = wctomb((char *)pc, wc)) <= 0) {
7040Sstevel@tonic-gate 				*pc = (unsigned char)wc;
7050Sstevel@tonic-gate 				j = 1;
7060Sstevel@tonic-gate 			}
7070Sstevel@tonic-gate 			pc += j;
7080Sstevel@tonic-gate 		}
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate 	return (write(d, chbuf, pc - chbuf));
7110Sstevel@tonic-gate #else /* !MBCHAR */
7120Sstevel@tonic-gate 	/* One byte always represents one tchar.  Easy! */
7130Sstevel@tonic-gate 	int	i;
7140Sstevel@tonic-gate 	unsigned char	*s;
7150Sstevel@tonic-gate 	tchar	*t;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate #ifdef	DBG
7180Sstevel@tonic-gate 	tprintf("Entering write_(d=%d, buf=0x%x, nch=%d);\n",
7190Sstevel@tonic-gate 	    d, buf, nch); /* Hope printf() doesn't call write_() itself! */
7200Sstevel@tonic-gate #endif /* DBG */
7210Sstevel@tonic-gate 	assert(nch <= sizeof (chbuf));
7220Sstevel@tonic-gate 	for (i = 0, t = buf, s = chbuf; i < nch; ++i) {
7230Sstevel@tonic-gate 	    *s++ = (char)((*t++)&0xff);
7240Sstevel@tonic-gate 	}
7250Sstevel@tonic-gate 	return (write(d, (char *)chbuf, nch));
7260Sstevel@tonic-gate #endif
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate #undef chbuf
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate #include <sys/types.h>
7320Sstevel@tonic-gate #include <sys/stat.h>	/* satruct stat */
7330Sstevel@tonic-gate #include <dirent.h>	/* DIR */
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate extern DIR *Dirp;
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate int
stat_(tchar * path,struct stat * buf)7380Sstevel@tonic-gate stat_(tchar *path, struct stat *buf)
7390Sstevel@tonic-gate {
7400Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	tstostr(chbuf, path);
7430Sstevel@tonic-gate 	return (stat((char *)chbuf, buf));
7440Sstevel@tonic-gate }
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate int
lstat_(tchar * path,struct stat * buf)7470Sstevel@tonic-gate lstat_(tchar *path, struct stat *buf)
7480Sstevel@tonic-gate {
7490Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	tstostr(chbuf, path);
7520Sstevel@tonic-gate 	return (lstat((char *)chbuf, buf));
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate int
chdir_(tchar * path)7560Sstevel@tonic-gate chdir_(tchar *path)
7570Sstevel@tonic-gate {
7580Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	tstostr(chbuf, path);
7610Sstevel@tonic-gate 	return (chdir((char *)chbuf));
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate tchar *
getwd_(tchar * path)7650Sstevel@tonic-gate getwd_(tchar *path)
7660Sstevel@tonic-gate {
7670Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7680Sstevel@tonic-gate 	int	rc;
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 	rc = (int)getwd((char *)chbuf);
7710Sstevel@tonic-gate 	if (rc == 0) {
7720Sstevel@tonic-gate 		return (0);
7730Sstevel@tonic-gate 	} else {
7740Sstevel@tonic-gate 		return (strtots(path, chbuf));
7750Sstevel@tonic-gate 	}
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate int
unlink_(tchar * path)7790Sstevel@tonic-gate unlink_(tchar *path)
7800Sstevel@tonic-gate {
7810Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 	tstostr(chbuf, path);
7840Sstevel@tonic-gate 	return (unlink((char *)chbuf));
7850Sstevel@tonic-gate }
7860Sstevel@tonic-gate 
7870Sstevel@tonic-gate DIR *
opendir_(tchar * dirname)7880Sstevel@tonic-gate opendir_(tchar *dirname)
7890Sstevel@tonic-gate {
7900Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	extern DIR *opendir();
7930Sstevel@tonic-gate 	DIR	*dir;
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	dir = opendir(tstostr(chbuf, dirname));
7960Sstevel@tonic-gate 	if (dir != NULL) {
7970Sstevel@tonic-gate 		setfd(dir->dd_fd);
7980Sstevel@tonic-gate 	}
7990Sstevel@tonic-gate 	return (Dirp = dir);
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate int
closedir_(DIR * dirp)8030Sstevel@tonic-gate closedir_(DIR *dirp)
8040Sstevel@tonic-gate {
8050Sstevel@tonic-gate 	int ret;
8060Sstevel@tonic-gate 	extern int closedir();
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	ret = closedir(dirp);
8090Sstevel@tonic-gate 	Dirp = NULL;
8100Sstevel@tonic-gate 	return (ret);
8110Sstevel@tonic-gate }
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate int
gethostname_(tchar * name,int namelen)8140Sstevel@tonic-gate gethostname_(tchar *name, int namelen)
8150Sstevel@tonic-gate {
8160Sstevel@tonic-gate 	char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	assert(namelen < BUFSIZ);
8190Sstevel@tonic-gate 	if (gethostname((char *)chbuf, sizeof (chbuf)) != 0) {
8200Sstevel@tonic-gate 		return (-1);
8210Sstevel@tonic-gate 	}
8220Sstevel@tonic-gate 	if (mbstotcs(name, chbuf, namelen) < 0) {
8230Sstevel@tonic-gate 		return (-1);
8240Sstevel@tonic-gate 	}
8250Sstevel@tonic-gate 	return (0); /* Succeeded. */
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate int
readlink_(tchar * path,tchar * buf,int bufsiz)8290Sstevel@tonic-gate readlink_(tchar *path, tchar *buf, int bufsiz)
8300Sstevel@tonic-gate {
8310Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
8320Sstevel@tonic-gate 	char	chpath[MAXPATHLEN + 1];
8330Sstevel@tonic-gate 	int	i;
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 	tstostr(chpath, path);
8360Sstevel@tonic-gate 	i = readlink(chpath, (char *)chbuf, sizeof (chbuf));
8370Sstevel@tonic-gate 	if (i < 0) {
8380Sstevel@tonic-gate 		return (-1);
8390Sstevel@tonic-gate 	}
8400Sstevel@tonic-gate 	chbuf[i] = (char)0;	/* readlink() doesn't put NULL. */
8410Sstevel@tonic-gate 	i = mbstotcs(buf, chbuf, bufsiz);
8420Sstevel@tonic-gate 	if (i < 0) {
8430Sstevel@tonic-gate 		return (-1);
8440Sstevel@tonic-gate 	}
8450Sstevel@tonic-gate 	return (i - 1); /* Return # of tchars EXCLUDING the terminating NULL. */
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate 
848*2182Schin /* checks that it's a number */
849*2182Schin 
850*2182Schin int
chkalldigit_(tchar * str)851*2182Schin chkalldigit_(tchar *str)
852*2182Schin {
853*2182Schin 	char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
854*2182Schin 	char *c = chbuf;
855*2182Schin 
856*2182Schin 	(void) tstostr(chbuf, str);
857*2182Schin 
858*2182Schin 	while (*c)
859*2182Schin 		if (!isdigit(*(c++)))
860*2182Schin 			return (-1);
861*2182Schin 
862*2182Schin 	return (0);
863*2182Schin }
864*2182Schin 
8650Sstevel@tonic-gate int
atoi_(tchar * str)8660Sstevel@tonic-gate atoi_(tchar *str)
8670Sstevel@tonic-gate {
8680Sstevel@tonic-gate 	char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	tstostr(chbuf, str);
8710Sstevel@tonic-gate 	return (atoi((char *)chbuf));
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate tchar *
simple(tchar * s)8750Sstevel@tonic-gate simple(tchar *s)
8760Sstevel@tonic-gate {
877356Smuffin 	tchar *sname = s;
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	while (1) {
8800Sstevel@tonic-gate 		if (any('/', sname)) {
8810Sstevel@tonic-gate 			while (*sname++ != '/')
8820Sstevel@tonic-gate 				;
8830Sstevel@tonic-gate 		} else {
8840Sstevel@tonic-gate 			return (sname);
8850Sstevel@tonic-gate 		}
8860Sstevel@tonic-gate 	}
8870Sstevel@tonic-gate }
888