xref: /illumos-gate/usr/src/cmd/csh/sh.tchar.c (revision 258f91c6)
17c478bd9Sstevel@tonic-gate /*
270a587ddSchin  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate /*
167c478bd9Sstevel@tonic-gate  * This module provides with system/library function substitutes for tchar
177c478bd9Sstevel@tonic-gate  * datatype. This also includes two conversion functions between tchar and
187c478bd9Sstevel@tonic-gate  * char arrays.
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * T. Kurosaka, Palo Alto, California, USA
217c478bd9Sstevel@tonic-gate  * March 1989
227c478bd9Sstevel@tonic-gate  *
237c478bd9Sstevel@tonic-gate  * Implementation Notes:
247c478bd9Sstevel@tonic-gate  *	Many functions defined here use a "char" buffer chbuf[].  In the
257c478bd9Sstevel@tonic-gate  * first attempt, there used to be only one chbuf defined as static
267c478bd9Sstevel@tonic-gate  * (private) variable and shared by these functions.  csh linked with that
277c478bd9Sstevel@tonic-gate  * version of this file misbehaved in interpreting "eval `tset ....`".
287c478bd9Sstevel@tonic-gate  * (in general, builtin function with back-quoted expression).
297c478bd9Sstevel@tonic-gate  *	This bug seemed to be caused by sharing of chbuf
307c478bd9Sstevel@tonic-gate  * by these functions simultanously (thru vfork() mechanism?).  We could not
317c478bd9Sstevel@tonic-gate  * identify which two functions interfere each other so we decided to
327c478bd9Sstevel@tonic-gate  * have each of these function its private instance of chbuf.
337c478bd9Sstevel@tonic-gate  * The size of chbuf[] might be much bigger than necessary for some functions.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate #ifdef DBG
367c478bd9Sstevel@tonic-gate #include <stdio.h>	/* For <assert.h> needs stderr defined. */
377c478bd9Sstevel@tonic-gate #else /* !DBG */
387c478bd9Sstevel@tonic-gate #define	NDEBUG		/* Disable assert(). */
397c478bd9Sstevel@tonic-gate #endif /* !DBG */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include <assert.h>
427c478bd9Sstevel@tonic-gate #include "sh.h"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #ifdef MBCHAR
457c478bd9Sstevel@tonic-gate #include <widec.h>	/* For wcsetno() */
467c478bd9Sstevel@tonic-gate #endif
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #include <sys/param.h>	/* MAXPATHLEN */
497c478bd9Sstevel@tonic-gate #include <fcntl.h>
507c478bd9Sstevel@tonic-gate #include <unistd.h>
517c478bd9Sstevel@tonic-gate 
52*258f91c6SToomas Soome bool	cflg;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * strtots(to, from): convert a char string 'from' into a tchar buffer 'to'.
567c478bd9Sstevel@tonic-gate  *	'to' is assumed to have the enough size to hold the conversion result.
577c478bd9Sstevel@tonic-gate  *	When 'to' is NOSTR(=(tchar *)0), strtots() attempts to allocate a space
587c478bd9Sstevel@tonic-gate  *	automatically using xalloc().  It is caller's responsibility to
5965b0c20eSnakanon  *	free the space allocated in this way, by calling xfree(ptr).
607c478bd9Sstevel@tonic-gate  *	In either case, strtots() returns the pointer to the conversion
617c478bd9Sstevel@tonic-gate  *	result (i.e. 'to', if 'to' wasn't NOSTR, or the allocated space.).
627c478bd9Sstevel@tonic-gate  *	When a conversion or allocateion failed,  NOSTR is returned.
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate tchar	*
strtots(tchar * to,char * from)667c478bd9Sstevel@tonic-gate strtots(tchar *to, char *from)
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate 	int	i;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	if (to == NOSTR) {	/* Need to xalloc(). */
717c478bd9Sstevel@tonic-gate 		int	i;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 		i = mbstotcs(NOSTR, from, 0);
747c478bd9Sstevel@tonic-gate 		if (i < 0) {
757c478bd9Sstevel@tonic-gate 			return (NOSTR);
767c478bd9Sstevel@tonic-gate 		}
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 		/* Allocate space for the resulting tchar array. */
797c478bd9Sstevel@tonic-gate 		to = (tchar *)xalloc(i * sizeof (tchar));
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 	i = mbstotcs(to, from, INT_MAX);
827c478bd9Sstevel@tonic-gate 	if (i < 0) {
837c478bd9Sstevel@tonic-gate 		return (NOSTR);
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 	return (to);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate char	*
tstostr(char * to,tchar * from)897c478bd9Sstevel@tonic-gate tstostr(char *to, tchar *from)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	tchar	*ptc;
927c478bd9Sstevel@tonic-gate 	wchar_t	wc;
937c478bd9Sstevel@tonic-gate 	char	*pmb;
947c478bd9Sstevel@tonic-gate 	int	len;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	if (to == (char *)NULL) {	/* Need to xalloc(). */
977c478bd9Sstevel@tonic-gate 		int	i;
987c478bd9Sstevel@tonic-gate 		int	i1;
997c478bd9Sstevel@tonic-gate 		char	junk[MB_LEN_MAX];
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 		/* Get sum of byte counts for each char in from. */
1027c478bd9Sstevel@tonic-gate 		i = 0;
1037c478bd9Sstevel@tonic-gate 		ptc = from;
1047c478bd9Sstevel@tonic-gate 		while (wc = (wchar_t)((*ptc++)&TRIM)) {
1057c478bd9Sstevel@tonic-gate 			if ((i1 = wctomb(junk, wc)) <= 0) {
1067c478bd9Sstevel@tonic-gate 				i1 = 1;
1077c478bd9Sstevel@tonic-gate 			}
1087c478bd9Sstevel@tonic-gate 			i += i1;
1097c478bd9Sstevel@tonic-gate 		}
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 		/* Allocate that much. */
1127c478bd9Sstevel@tonic-gate 		to = (char *)xalloc(i + 1);
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	ptc = from;
1167c478bd9Sstevel@tonic-gate 	pmb = to;
1177c478bd9Sstevel@tonic-gate 	while (wc = (wchar_t)((*ptc++)&TRIM)) {
1187c478bd9Sstevel@tonic-gate 		if ((len = wctomb(pmb, wc)) <= 0) {
1197c478bd9Sstevel@tonic-gate 			*pmb = (unsigned char)wc;
1207c478bd9Sstevel@tonic-gate 			len = 1;
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 		pmb += len;
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 	*pmb = (char)0;
1257c478bd9Sstevel@tonic-gate 	return (to);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate /*
1297c478bd9Sstevel@tonic-gate  * mbstotcs(to, from, tosize) is similar to strtots() except that
1307c478bd9Sstevel@tonic-gate  * this returns # of tchars of the resulting tchar string.
1317c478bd9Sstevel@tonic-gate  * When NULL is give as the destination, no real conversion is carried out,
1327c478bd9Sstevel@tonic-gate  * and the function reports how many tchar characters would be made in
1337c478bd9Sstevel@tonic-gate  * the converted result including the terminating 0.
1347c478bd9Sstevel@tonic-gate  *	tchar	*to;	- Destination buffer, or NULL.
1357c478bd9Sstevel@tonic-gate  *	char	*from;	- Source string.
1367c478bd9Sstevel@tonic-gate  *	int	tosize; - Size of to, in terms of # of tchars.
1377c478bd9Sstevel@tonic-gate  */
1387c478bd9Sstevel@tonic-gate int
mbstotcs(tchar * to,char * from,int tosize)1397c478bd9Sstevel@tonic-gate mbstotcs(tchar *to, char *from, int tosize)
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate 	tchar	*ptc = to;
1427c478bd9Sstevel@tonic-gate 	char	*pmb = from;
1437c478bd9Sstevel@tonic-gate 	wchar_t	wc;
1447c478bd9Sstevel@tonic-gate 	int	chcnt = 0;
1457c478bd9Sstevel@tonic-gate 	int	j;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/* Just count how many tchar would be in the result. */
1497c478bd9Sstevel@tonic-gate 	if (to == (tchar *)NULL) {
1507c478bd9Sstevel@tonic-gate 		while (*pmb) {
1517c478bd9Sstevel@tonic-gate 			if ((j = mbtowc(&wc, pmb, MB_CUR_MAX)) <= 0) {
1527c478bd9Sstevel@tonic-gate 				j = 1;
1537c478bd9Sstevel@tonic-gate 			}
1547c478bd9Sstevel@tonic-gate 			pmb += j;
1557c478bd9Sstevel@tonic-gate 			chcnt++;
1567c478bd9Sstevel@tonic-gate 		}
1577c478bd9Sstevel@tonic-gate 		chcnt++;	/* For terminator. */
1587c478bd9Sstevel@tonic-gate 		return (chcnt);	/* # of chars including terminating zero. */
1597c478bd9Sstevel@tonic-gate 	} else {	/* Do the real conversion. */
1607c478bd9Sstevel@tonic-gate 		while (*pmb) {
1617c478bd9Sstevel@tonic-gate 			if ((j = mbtowc(&wc, pmb, MB_CUR_MAX)) <= 0) {
1627c478bd9Sstevel@tonic-gate 				wc = (unsigned char)*pmb;
1637c478bd9Sstevel@tonic-gate 				j = 1;
1647c478bd9Sstevel@tonic-gate 			}
1657c478bd9Sstevel@tonic-gate 			pmb += j;
1667c478bd9Sstevel@tonic-gate 			*(ptc++) = (tchar)wc;
1677c478bd9Sstevel@tonic-gate 			if (++chcnt >= tosize) {
1687c478bd9Sstevel@tonic-gate 				break;
1697c478bd9Sstevel@tonic-gate 			}
1707c478bd9Sstevel@tonic-gate 		}
1717c478bd9Sstevel@tonic-gate 		/* Terminate with zero only when space is left. */
1727c478bd9Sstevel@tonic-gate 		if (chcnt < tosize) {
1737c478bd9Sstevel@tonic-gate 			*ptc = (tchar)0;
1747c478bd9Sstevel@tonic-gate 			++chcnt;
1757c478bd9Sstevel@tonic-gate 		}
1767c478bd9Sstevel@tonic-gate 		return (chcnt); /* # of chars including terminating zero. */
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate /* tchar version of STRING functions. */
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * Returns the number of
1857c478bd9Sstevel@tonic-gate  * non-NULL tchar elements in tchar string argument.
1867c478bd9Sstevel@tonic-gate  */
1877c478bd9Sstevel@tonic-gate int
strlen_(tchar * s)1887c478bd9Sstevel@tonic-gate strlen_(tchar *s)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	int n;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	n = 0;
1937c478bd9Sstevel@tonic-gate 	while (*s++) {
1947c478bd9Sstevel@tonic-gate 		n++;
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 	return (n);
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate  * Concatenate tchar string s2 on the end of s1.  S1's space must be large
2017c478bd9Sstevel@tonic-gate  * enough.  Return s1.
2027c478bd9Sstevel@tonic-gate  */
2037c478bd9Sstevel@tonic-gate tchar *
strcat_(tchar * s1,tchar * s2)2047c478bd9Sstevel@tonic-gate strcat_(tchar *s1, tchar *s2)
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	tchar *os1;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	os1 = s1;
2097c478bd9Sstevel@tonic-gate 	while (*s1++)
2107c478bd9Sstevel@tonic-gate 		;
2117c478bd9Sstevel@tonic-gate 	--s1;
2127c478bd9Sstevel@tonic-gate 	while (*s1++ = *s2++)
2137c478bd9Sstevel@tonic-gate 		;
2147c478bd9Sstevel@tonic-gate 	return (os1);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate /*
2187c478bd9Sstevel@tonic-gate  * Compare tchar strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
2197c478bd9Sstevel@tonic-gate  * BUGS: Comparison between two characters are done by subtracting two chars
2207c478bd9Sstevel@tonic-gate  *	after converting each to an unsigned long int value.  It might not make
2217c478bd9Sstevel@tonic-gate  *	a whole lot of sense to do that if the characters are in represented
2227c478bd9Sstevel@tonic-gate  *	as wide characters and the two characters belong to different codesets.
2237c478bd9Sstevel@tonic-gate  *	Therefore, this function should be used only to test the equallness.
2247c478bd9Sstevel@tonic-gate  */
2257c478bd9Sstevel@tonic-gate int
strcmp_(tchar * s1,tchar * s2)2267c478bd9Sstevel@tonic-gate strcmp_(tchar *s1, tchar *s2)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 	while (*s1 == *s2++) {
2297c478bd9Sstevel@tonic-gate 		if (*s1++ == (tchar)0) {
2307c478bd9Sstevel@tonic-gate 			return (0);
2317c478bd9Sstevel@tonic-gate 		}
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 	return (((unsigned long)*s1) - ((unsigned long)*(--s2)));
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /*
2377c478bd9Sstevel@tonic-gate  * This is only used in sh.glob.c for sorting purpose.
2387c478bd9Sstevel@tonic-gate  */
2397c478bd9Sstevel@tonic-gate int
strcoll_(tchar * s1,tchar * s2)2407c478bd9Sstevel@tonic-gate strcoll_(tchar *s1, tchar *s2)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	char buf1[BUFSIZ];
2437c478bd9Sstevel@tonic-gate 	char buf2[BUFSIZ];
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	tstostr(buf1, s1);
2467c478bd9Sstevel@tonic-gate 	tstostr(buf2, s2);
2477c478bd9Sstevel@tonic-gate 	return (strcoll(buf1, buf2));
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate /*
2517c478bd9Sstevel@tonic-gate  * Copy tchar string s2 to s1.  s1 must be large enough.
2527c478bd9Sstevel@tonic-gate  * return s1
2537c478bd9Sstevel@tonic-gate  */
2547c478bd9Sstevel@tonic-gate tchar *
strcpy_(tchar * s1,tchar * s2)2557c478bd9Sstevel@tonic-gate strcpy_(tchar *s1, tchar *s2)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate 	tchar *os1;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	os1 = s1;
2607c478bd9Sstevel@tonic-gate 	while (*s1++ = *s2++)
2617c478bd9Sstevel@tonic-gate 		;
2627c478bd9Sstevel@tonic-gate 	return (os1);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate  * Return the ptr in sp at which the character c appears;
2677c478bd9Sstevel@tonic-gate  * NULL if not found
2687c478bd9Sstevel@tonic-gate  */
2697c478bd9Sstevel@tonic-gate tchar *
index_(tchar * sp,tchar c)2707c478bd9Sstevel@tonic-gate index_(tchar *sp, tchar c)
2717c478bd9Sstevel@tonic-gate {
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	do {
2747c478bd9Sstevel@tonic-gate 		if (*sp == c) {
2757c478bd9Sstevel@tonic-gate 			return (sp);
2767c478bd9Sstevel@tonic-gate 		}
2777c478bd9Sstevel@tonic-gate 	} while (*sp++);
2787c478bd9Sstevel@tonic-gate 	return (NULL);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate  * Return the ptr in sp at which the character c last
2837c478bd9Sstevel@tonic-gate  * appears; NOSTR if not found
2847c478bd9Sstevel@tonic-gate  */
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate tchar *
rindex_(tchar * sp,tchar c)2877c478bd9Sstevel@tonic-gate rindex_(tchar *sp, tchar c)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate 	tchar *r;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	r = NOSTR;
2927c478bd9Sstevel@tonic-gate 	do {
2937c478bd9Sstevel@tonic-gate 		if (*sp == c) {
2947c478bd9Sstevel@tonic-gate 			r = sp;
2957c478bd9Sstevel@tonic-gate 		}
2967c478bd9Sstevel@tonic-gate 	} while (*sp++);
2977c478bd9Sstevel@tonic-gate 	return (r);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate /* Additional misc functions. */
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate /* Calculate the display width of a string.  */
3036c02b4a4Smuffin int
tswidth(tchar * ts)3047c478bd9Sstevel@tonic-gate tswidth(tchar *ts)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate #ifdef MBCHAR
3077c478bd9Sstevel@tonic-gate 	wchar_t	tc;
3087c478bd9Sstevel@tonic-gate 	int	w = 0;
3097c478bd9Sstevel@tonic-gate 	int	p_col;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	while (tc = *ts++) {
3127c478bd9Sstevel@tonic-gate 		if ((p_col = wcwidth((wchar_t)tc)) > 0)
3137c478bd9Sstevel@tonic-gate 			w += p_col;
3147c478bd9Sstevel@tonic-gate 	}
3157c478bd9Sstevel@tonic-gate 	return (w);
3167c478bd9Sstevel@tonic-gate #else /* !MBCHAR --- one char always occupies one column. */
3177c478bd9Sstevel@tonic-gate 	return (strlen_(ts));
3187c478bd9Sstevel@tonic-gate #endif
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate  * Two getenv() substitute functions.  They differ in the type of arguments.
3237c478bd9Sstevel@tonic-gate  * BUGS: Both returns the pointer to an allocated space where the env var's
3247c478bd9Sstevel@tonic-gate  *	values is stored.  This space is freed automatically on the successive
3257c478bd9Sstevel@tonic-gate  *	call of	either function.  Therefore the caller must copy the contents
3267c478bd9Sstevel@tonic-gate  *	if it needs to access two env vars.  There is an arbitary limitation
3277c478bd9Sstevel@tonic-gate  *	on the number of chars of a env var name.
3287c478bd9Sstevel@tonic-gate  */
3297c478bd9Sstevel@tonic-gate #define	LONGEST_ENVVARNAME	256		/* Too big? */
3307c478bd9Sstevel@tonic-gate tchar *
getenv_(tchar * name_)3317c478bd9Sstevel@tonic-gate getenv_(tchar *name_)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate 	char	name[LONGEST_ENVVARNAME * MB_LEN_MAX];
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	assert(strlen_(name_) < LONGEST_ENVVARNAME);
3367c478bd9Sstevel@tonic-gate 	return (getenvs_(tstostr(name, name_)));
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate tchar *
getenvs_(char * name)3407c478bd9Sstevel@tonic-gate getenvs_(char *name)
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate 	static tchar	*pbuf = (tchar *)NULL;
3437c478bd9Sstevel@tonic-gate 	char	*val;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	if (pbuf) {
34665b0c20eSnakanon 		xfree(pbuf);
3477c478bd9Sstevel@tonic-gate 		pbuf = NOSTR;
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 	val = getenv(name);
3507c478bd9Sstevel@tonic-gate 	if (val == (char *)NULL) {
3517c478bd9Sstevel@tonic-gate 		return (NOSTR);
3527c478bd9Sstevel@tonic-gate 	}
3537c478bd9Sstevel@tonic-gate 	return (pbuf = strtots(NOSTR, val));
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate /* Followings are the system call interface for tchar strings. */
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate  * creat() and open() replacement.
3607c478bd9Sstevel@tonic-gate  * BUGS: An unusually long file name could be dangerous.
3617c478bd9Sstevel@tonic-gate  */
3627c478bd9Sstevel@tonic-gate int
creat_(tchar * name_,int mode)3637c478bd9Sstevel@tonic-gate creat_(tchar *name_, int mode)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate 	int fd;
3667c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	tstostr(chbuf, name_);
3697c478bd9Sstevel@tonic-gate 	fd = creat((char *)chbuf, mode);
3707c478bd9Sstevel@tonic-gate 	if (fd != -1) {
3717c478bd9Sstevel@tonic-gate 		setfd(fd);
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	return (fd);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate /*VARARGS2*/
3777c478bd9Sstevel@tonic-gate int
open_(path_,flags,mode)3787c478bd9Sstevel@tonic-gate open_(path_, flags, mode)
3797c478bd9Sstevel@tonic-gate 	tchar 	*path_;
3807c478bd9Sstevel@tonic-gate 	int	flags;
3817c478bd9Sstevel@tonic-gate 	int	mode; /* May be omitted. */
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
3847c478bd9Sstevel@tonic-gate 	int fd;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	tstostr(chbuf, path_);
3877c478bd9Sstevel@tonic-gate 	fd = open((char *)chbuf, flags, mode);
3887c478bd9Sstevel@tonic-gate 	if (fd != -1) {
3897c478bd9Sstevel@tonic-gate 		setfd(fd);
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 	return (fd);
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate /*
3957c478bd9Sstevel@tonic-gate  * mkstemp replacement
3967c478bd9Sstevel@tonic-gate  */
3977c478bd9Sstevel@tonic-gate int
mkstemp_(tchar * name_)3987c478bd9Sstevel@tonic-gate mkstemp_(tchar *name_)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate 	int fd;
4017c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	tstostr(chbuf, name_);
4047c478bd9Sstevel@tonic-gate 	fd = mkstemp((char *)chbuf);
4057c478bd9Sstevel@tonic-gate 	if (fd != -1) {
4067c478bd9Sstevel@tonic-gate 		setfd(fd);
4077c478bd9Sstevel@tonic-gate 		strtots(name_, chbuf);
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 	return (fd);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate  * read() and write() reaplacement.
4147c478bd9Sstevel@tonic-gate  *	int        d;
4157c478bd9Sstevel@tonic-gate  *	tchar      *buf;  - where the result be stored.  Not NULL terminated.
4167c478bd9Sstevel@tonic-gate  *	int        nchreq; - # of tchars requrested.
4177c478bd9Sstevel@tonic-gate  */
4187c478bd9Sstevel@tonic-gate int
read_(int d,tchar * buf,int nchreq)4197c478bd9Sstevel@tonic-gate read_(int d, tchar *buf, int nchreq)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	unsigned char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
4227c478bd9Sstevel@tonic-gate #ifdef MBCHAR
4237c478bd9Sstevel@tonic-gate 	/*
4247c478bd9Sstevel@tonic-gate 	 * We would have to read more than tchar bytes
4257c478bd9Sstevel@tonic-gate 	 * when there are multibyte characters in the file.
4267c478bd9Sstevel@tonic-gate 	 */
4277c478bd9Sstevel@tonic-gate 	int	i, j, fflags;
4287c478bd9Sstevel@tonic-gate 	unsigned char	*s;	/* Byte being scanned for a multibyte char. */
4297c478bd9Sstevel@tonic-gate 	/* Points to the pos where next read() to read the data into. */
4307c478bd9Sstevel@tonic-gate 	unsigned char	*p;
4317c478bd9Sstevel@tonic-gate 	tchar	*t;
4327c478bd9Sstevel@tonic-gate 	wchar_t		wc;
4337c478bd9Sstevel@tonic-gate 	int		b_len;
4347c478bd9Sstevel@tonic-gate 	int		nchread = 0; /* Count how many bytes has been read. */
4357c478bd9Sstevel@tonic-gate 	int		nbytread = 0; /* Total # of bytes read. */
4367c478bd9Sstevel@tonic-gate 	/* # of bytes needed to complete the last char just read. */
4377c478bd9Sstevel@tonic-gate 	int		delta;
4387c478bd9Sstevel@tonic-gate 	unsigned char	*q;	/* q points to the first invalid byte. */
43965b0c20eSnakanon 	int		mb_cur_max = MB_CUR_MAX;
4407c478bd9Sstevel@tonic-gate #ifdef DBG
4417c478bd9Sstevel@tonic-gate 	tprintf("Entering read_(d=%d, buf=0x%x, nchreq=%d);\n",
4427c478bd9Sstevel@tonic-gate 	    d, buf, nchreq);
4437c478bd9Sstevel@tonic-gate #endif /* DBG */
4447c478bd9Sstevel@tonic-gate 	/*
4457c478bd9Sstevel@tonic-gate 	 *	Step 1: We collect the exact number of bytes that make
4467c478bd9Sstevel@tonic-gate 	 *	nchreq characters into chbuf.
4477c478bd9Sstevel@tonic-gate 	 *	We must be careful not to read too many bytes as we
4487c478bd9Sstevel@tonic-gate 	 *	cannot push back such over-read bytes.
4497c478bd9Sstevel@tonic-gate 	 *	The idea we use here is that n multibyte characters are stored
4507c478bd9Sstevel@tonic-gate 	 *	in no less than n but less than n*MB_CUR_MAX bytes.
4517c478bd9Sstevel@tonic-gate 	 */
4527c478bd9Sstevel@tonic-gate 	assert(nchreq <= BUFSIZ);
4537c478bd9Sstevel@tonic-gate 	delta = 0;
4547c478bd9Sstevel@tonic-gate 	p = s = chbuf;
4557c478bd9Sstevel@tonic-gate 	t = buf;
4567c478bd9Sstevel@tonic-gate 	while (nchread < nchreq) {
4577c478bd9Sstevel@tonic-gate 		int		m;  /* # of bytes to try to read this time. */
4587c478bd9Sstevel@tonic-gate 		int		k;  /* # of bytes successfully read. */
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate retry:
4617c478bd9Sstevel@tonic-gate 		/*
4627c478bd9Sstevel@tonic-gate 		 * Let's say the (N+1)'th byte bN is actually the first
4637c478bd9Sstevel@tonic-gate 		 * byte of a three-byte character c.
4647c478bd9Sstevel@tonic-gate 		 * In that case, p, s, q look like this:
4657c478bd9Sstevel@tonic-gate 		 *
4667c478bd9Sstevel@tonic-gate 		 *		/-- already read--\ /-- not yet read --\
4677c478bd9Sstevel@tonic-gate 		 * chbuf[]:	b0 b1 ..... bN bN+1 bN+2 bN+2 ...
4687c478bd9Sstevel@tonic-gate 		 *		^		^	^
4697c478bd9Sstevel@tonic-gate 		 *		|		|	|
4707c478bd9Sstevel@tonic-gate 		 *		p		s	q
4717c478bd9Sstevel@tonic-gate 		 *				\----------/
4727c478bd9Sstevel@tonic-gate 		 *				c hasn't been completed
4737c478bd9Sstevel@tonic-gate 		 *
4747c478bd9Sstevel@tonic-gate 		 * Just after the next read(), p and q will be adavanced to:
4757c478bd9Sstevel@tonic-gate 		 *
4767c478bd9Sstevel@tonic-gate 		 *	/-- already read-----------------------\ /-- not yet -
4777c478bd9Sstevel@tonic-gate 		 * chbuf[]: b0 b1 ..... bN bN+1 bN+2 bN+2 ... bX bX+1 bX+2...
4787c478bd9Sstevel@tonic-gate 		 *			^	^		 ^
4797c478bd9Sstevel@tonic-gate 		 *			|	|		 |
4807c478bd9Sstevel@tonic-gate 		 *			s	p		 q
4817c478bd9Sstevel@tonic-gate 		 *			\----------/
4827c478bd9Sstevel@tonic-gate 		 *			 c has been completed
4837c478bd9Sstevel@tonic-gate 		 *			 but hasn't been scanned
4847c478bd9Sstevel@tonic-gate 		 */
4857c478bd9Sstevel@tonic-gate 		m = nchreq - nchread;
4867c478bd9Sstevel@tonic-gate 		assert(p + m < chbuf + sizeof (chbuf));
4877c478bd9Sstevel@tonic-gate 		k = read(d, p, m);
4887c478bd9Sstevel@tonic-gate 		/*
4897c478bd9Sstevel@tonic-gate 		 * when child sets O_NDELAY or O_NONBLOCK on stdin
4907c478bd9Sstevel@tonic-gate 		 * and exits and we are interactive then turn the modes off
4917c478bd9Sstevel@tonic-gate 		 * and retry
4927c478bd9Sstevel@tonic-gate 		 */
4937c478bd9Sstevel@tonic-gate 		if (k == 0) {
4947c478bd9Sstevel@tonic-gate 			if ((intty && !onelflg && !cflg) &&
4957c478bd9Sstevel@tonic-gate 			    ((fflags = fcntl(d, F_GETFL, 0)) & O_NDELAY)) {
4967c478bd9Sstevel@tonic-gate 				fflags &= ~O_NDELAY;
4977c478bd9Sstevel@tonic-gate 				fcntl(d, F_SETFL, fflags);
4987c478bd9Sstevel@tonic-gate 				goto retry;
4997c478bd9Sstevel@tonic-gate 			}
5007c478bd9Sstevel@tonic-gate 		} else if (k < 0) {
5017c478bd9Sstevel@tonic-gate 			if (errno == EAGAIN) {
5027c478bd9Sstevel@tonic-gate 				fflags = fcntl(d, F_GETFL, 0);
5037c478bd9Sstevel@tonic-gate 				fflags &= ~O_NONBLOCK;
5047c478bd9Sstevel@tonic-gate 				fcntl(d, F_SETFL, fflags);
5057c478bd9Sstevel@tonic-gate 				goto retry;
5067c478bd9Sstevel@tonic-gate 			}
5077c478bd9Sstevel@tonic-gate 			return (-1);
5087c478bd9Sstevel@tonic-gate 		}
5097c478bd9Sstevel@tonic-gate 		nbytread += k;
5107c478bd9Sstevel@tonic-gate 		q = p + k;
5117c478bd9Sstevel@tonic-gate 		delta = 0;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 		/* Try scaning characters in s..q-1 */
5147c478bd9Sstevel@tonic-gate 		while (s < q) {
5157c478bd9Sstevel@tonic-gate 			/* Convert the collected bytes into tchar array. */
5167c478bd9Sstevel@tonic-gate 			if (*s == 0) {
5177c478bd9Sstevel@tonic-gate 				/* NUL is treated as a normal char here. */
5187c478bd9Sstevel@tonic-gate 				*t++ = 0;
5197c478bd9Sstevel@tonic-gate 				s++;
5207c478bd9Sstevel@tonic-gate 				nchread++;
5217c478bd9Sstevel@tonic-gate 				continue;
5227c478bd9Sstevel@tonic-gate 			}
5237c478bd9Sstevel@tonic-gate 
52465b0c20eSnakanon 			if ((b_len = q - s) > mb_cur_max) {
52565b0c20eSnakanon 				b_len = mb_cur_max;
5267c478bd9Sstevel@tonic-gate 			}
5277c478bd9Sstevel@tonic-gate 			if ((j = mbtowc(&wc, (char *)s, b_len)) <=  0) {
52865b0c20eSnakanon 				if (mb_cur_max > 1 && b_len < mb_cur_max) {
5297c478bd9Sstevel@tonic-gate 					/*
5307c478bd9Sstevel@tonic-gate 					 * Needs more byte to complete this char
5317c478bd9Sstevel@tonic-gate 					 * In order to read() more than delta
5327c478bd9Sstevel@tonic-gate 					 * bytes.
5337c478bd9Sstevel@tonic-gate 					 */
5347c478bd9Sstevel@tonic-gate 					break;
5357c478bd9Sstevel@tonic-gate 				}
5367c478bd9Sstevel@tonic-gate 				wc = (unsigned char)*s;
5377c478bd9Sstevel@tonic-gate 				j = 1;
5387c478bd9Sstevel@tonic-gate 			}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 			*t++ = wc;
5417c478bd9Sstevel@tonic-gate 			nchread++;
5427c478bd9Sstevel@tonic-gate 			s += j;
5437c478bd9Sstevel@tonic-gate 		}
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 		if (k < m) {
5467c478bd9Sstevel@tonic-gate 			/* We've read as many bytes as possible. */
5477c478bd9Sstevel@tonic-gate 			while (s < q) {
54865b0c20eSnakanon 				if ((b_len = q - s) > mb_cur_max) {
54965b0c20eSnakanon 					b_len = mb_cur_max;
5507c478bd9Sstevel@tonic-gate 				}
5517c478bd9Sstevel@tonic-gate 				if ((j = mbtowc(&wc, (char *)s, b_len)) <=  0) {
5527c478bd9Sstevel@tonic-gate 					wc = (unsigned char)*s;
5537c478bd9Sstevel@tonic-gate 					j = 1;
5547c478bd9Sstevel@tonic-gate 				}
5557c478bd9Sstevel@tonic-gate 				*t++ = wc;
5567c478bd9Sstevel@tonic-gate 				nchread++;
5577c478bd9Sstevel@tonic-gate 				s += j;
5587c478bd9Sstevel@tonic-gate 			}
5597c478bd9Sstevel@tonic-gate 			return (nchread);
5607c478bd9Sstevel@tonic-gate 		}
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 		p = q;
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 
56565b0c20eSnakanon 	if (mb_cur_max == 1 || (delta = q - s) == 0) {
5667c478bd9Sstevel@tonic-gate 		return (nchread);
5677c478bd9Sstevel@tonic-gate 	}
5687c478bd9Sstevel@tonic-gate 
56965b0c20eSnakanon 	/*
57065b0c20eSnakanon 	 * We may have (MB_CUR_MAX - 1) unread data in the buffer.
57165b0c20eSnakanon 	 * Here, the last converted data was an illegal character which was
57265b0c20eSnakanon 	 * treated as one byte character. We don't know at this point
57365b0c20eSnakanon 	 * whether or not the remaining data is in legal sequence.
57465b0c20eSnakanon 	 * We first attempt to convert the remaining data.
57565b0c20eSnakanon 	 */
57665b0c20eSnakanon 	do {
57765b0c20eSnakanon 		if ((j = mbtowc(&wc, (char *)s, delta)) <= 0)
57865b0c20eSnakanon 			break;
57965b0c20eSnakanon 		*t++ = wc;
58065b0c20eSnakanon 		nchread++;
58165b0c20eSnakanon 		s += j;
58265b0c20eSnakanon 		delta -= j;
58365b0c20eSnakanon 	} while (delta > 0);
58465b0c20eSnakanon 
58565b0c20eSnakanon 	if (delta == 0)
5867c478bd9Sstevel@tonic-gate 		return (nchread);
5877c478bd9Sstevel@tonic-gate 
58865b0c20eSnakanon 	/*
58965b0c20eSnakanon 	 * There seem to be ugly sequence in the buffer. Fill up till
59065b0c20eSnakanon 	 * mb_cur_max and see if we can get a right sequence.
59165b0c20eSnakanon 	 */
59265b0c20eSnakanon 	while (delta < mb_cur_max) {
5937c478bd9Sstevel@tonic-gate 		assert((q + 1) < (chbuf + sizeof (chbuf)));
59465b0c20eSnakanon 		if (read(d, q, 1) != 1)
5957c478bd9Sstevel@tonic-gate 			break;
59665b0c20eSnakanon 		delta++;
59765b0c20eSnakanon 		q++;
5987c478bd9Sstevel@tonic-gate 		if (mbtowc(&wc, (char *)s, delta) > 0) {
5997c478bd9Sstevel@tonic-gate 			*t = wc;
6007c478bd9Sstevel@tonic-gate 			return (nchread + 1);
6017c478bd9Sstevel@tonic-gate 		}
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 
60465b0c20eSnakanon 	/*
60565b0c20eSnakanon 	 * no luck. we have filled MB_CUR_MAX bytes in the buffer.
60665b0c20eSnakanon 	 * Ideally we should return with leaving such data off and
60765b0c20eSnakanon 	 * put them into a local buffer for next read, but we don't
60865b0c20eSnakanon 	 * have such.
60965b0c20eSnakanon 	 * So, stop reading further, and treat them as all single
61065b0c20eSnakanon 	 * byte characters.
61165b0c20eSnakanon 	 */
6127c478bd9Sstevel@tonic-gate 	while (s < q) {
61365b0c20eSnakanon 		b_len = q - s;
6147c478bd9Sstevel@tonic-gate 		if ((j = mbtowc(&wc, (char *)s, b_len)) <=  0) {
6157c478bd9Sstevel@tonic-gate 			wc = (unsigned char)*s;
6167c478bd9Sstevel@tonic-gate 			j = 1;
6177c478bd9Sstevel@tonic-gate 		}
6187c478bd9Sstevel@tonic-gate 		*t++ = wc;
6197c478bd9Sstevel@tonic-gate 		nchread++;
6207c478bd9Sstevel@tonic-gate 		s += j;
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 	return (nchread);
62365b0c20eSnakanon 
6247c478bd9Sstevel@tonic-gate #else /* !MBCHAR */
6257c478bd9Sstevel@tonic-gate 	/* One byte always represents one tchar.  Easy! */
6267c478bd9Sstevel@tonic-gate 	int		i;
6277c478bd9Sstevel@tonic-gate 	unsigned char	*s;
6287c478bd9Sstevel@tonic-gate 	tchar		*t;
6297c478bd9Sstevel@tonic-gate 	int		nchread;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate #ifdef DBG
6327c478bd9Sstevel@tonic-gate 	tprintf("Entering read_(d=%d, buf=0x%x, nchreq=%d);\n",
6337c478bd9Sstevel@tonic-gate 	    d, buf, nchreq);
6347c478bd9Sstevel@tonic-gate #endif /* DBG */
6357c478bd9Sstevel@tonic-gate 	assert(nchreq <= BUFSIZ);
6367c478bd9Sstevel@tonic-gate retry:
6377c478bd9Sstevel@tonic-gate 	nchread = read(d, (char *)chbuf, nchreq);
6387c478bd9Sstevel@tonic-gate 	/*
6397c478bd9Sstevel@tonic-gate 	 * when child sets O_NDELAY or O_NONBLOCK on stdin
6407c478bd9Sstevel@tonic-gate 	 * and exits and we are interactive then turn the modes off
6417c478bd9Sstevel@tonic-gate 	 * and retry
6427c478bd9Sstevel@tonic-gate 	 */
6437c478bd9Sstevel@tonic-gate 	if (nchread == 0) {
6447c478bd9Sstevel@tonic-gate 		if ((intty && !onelflg && !cflg) &&
6457c478bd9Sstevel@tonic-gate 		    ((fflags = fcntl(d, F_GETFL, 0)) & O_NDELAY)) {
6467c478bd9Sstevel@tonic-gate 			fflags &= ~O_NDELAY;
6477c478bd9Sstevel@tonic-gate 			fcntl(d, F_SETFL, fflags);
6487c478bd9Sstevel@tonic-gate 			goto retry;
6497c478bd9Sstevel@tonic-gate 		}
6507c478bd9Sstevel@tonic-gate 	} else if (nchread < 0) {
6517c478bd9Sstevel@tonic-gate 		if (errno == EAGAIN) {
6527c478bd9Sstevel@tonic-gate 			fflags = fcntl(d, F_GETFL, 0);
6537c478bd9Sstevel@tonic-gate 			fflags &= ~O_NONBLOCK;
6547c478bd9Sstevel@tonic-gate 			fcntl(d, F_SETFL, fflags);
6557c478bd9Sstevel@tonic-gate 			goto retry;
6567c478bd9Sstevel@tonic-gate 		}
6577c478bd9Sstevel@tonic-gate 		len = 0;
6587c478bd9Sstevel@tonic-gate 	} else {
6597c478bd9Sstevel@tonic-gate 		for (i = 0, t = buf, s = chbuf; i < nchread; ++i) {
6607c478bd9Sstevel@tonic-gate 		    *t++ = ((tchar)*s++);
6617c478bd9Sstevel@tonic-gate 		}
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 	return (nchread);
6647c478bd9Sstevel@tonic-gate #endif
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate /*
6687c478bd9Sstevel@tonic-gate  * BUG: write_() returns -1 on failure, or # of BYTEs it has written.
6697c478bd9Sstevel@tonic-gate  *	For consistency and symmetry, it should return the number of
6707c478bd9Sstevel@tonic-gate  *	characters it has actually written, but that is technically
6717c478bd9Sstevel@tonic-gate  *	difficult although not impossible.  Anyway, the return
6727c478bd9Sstevel@tonic-gate  *	value of write() has never been used by the original csh,
6737c478bd9Sstevel@tonic-gate  *	so this bug should be OK.
6747c478bd9Sstevel@tonic-gate  */
6757c478bd9Sstevel@tonic-gate int
write_(int d,tchar * buf,int nch)6767c478bd9Sstevel@tonic-gate write_(int d, tchar *buf, int nch)
6777c478bd9Sstevel@tonic-gate {
6787c478bd9Sstevel@tonic-gate 	unsigned char chbuf[BUFSIZ*MB_LEN_MAX]; /* General use buffer. */
6797c478bd9Sstevel@tonic-gate #ifdef MBCHAR
6807c478bd9Sstevel@tonic-gate 	tchar		*pt;
6817c478bd9Sstevel@tonic-gate 	unsigned char	*pc;
6827c478bd9Sstevel@tonic-gate 	wchar_t		wc;
6837c478bd9Sstevel@tonic-gate 	int		i, j;
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate #ifdef	DBG
6867c478bd9Sstevel@tonic-gate 	tprintf("Entering write_(d=%d, buf=0x%x, nch=%d);\n",
6877c478bd9Sstevel@tonic-gate 	    d, buf, nch); /* Hope printf() doesn't call write_() itself! */
6887c478bd9Sstevel@tonic-gate #endif /* DBG */
6897c478bd9Sstevel@tonic-gate 	assert(nch * MB_CUR_MAX < sizeof (chbuf));
6907c478bd9Sstevel@tonic-gate 	i = nch;
6917c478bd9Sstevel@tonic-gate 	pt = buf;
6927c478bd9Sstevel@tonic-gate 	pc = chbuf;
6937c478bd9Sstevel@tonic-gate 	while (i--) {
6947c478bd9Sstevel@tonic-gate 		/*
6957c478bd9Sstevel@tonic-gate 		 * Convert to tchar string.
6967c478bd9Sstevel@tonic-gate 		 * NUL is treated as normal char here.
6977c478bd9Sstevel@tonic-gate 		 */
6987c478bd9Sstevel@tonic-gate 		wc = (wchar_t)((*pt++)&TRIM);
6997c478bd9Sstevel@tonic-gate 		if (wc == (wchar_t)0) {
7007c478bd9Sstevel@tonic-gate 			*pc++ = 0;
7017c478bd9Sstevel@tonic-gate 		} else {
7027c478bd9Sstevel@tonic-gate 			if ((j = wctomb((char *)pc, wc)) <= 0) {
7037c478bd9Sstevel@tonic-gate 				*pc = (unsigned char)wc;
7047c478bd9Sstevel@tonic-gate 				j = 1;
7057c478bd9Sstevel@tonic-gate 			}
7067c478bd9Sstevel@tonic-gate 			pc += j;
7077c478bd9Sstevel@tonic-gate 		}
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 	return (write(d, chbuf, pc - chbuf));
7107c478bd9Sstevel@tonic-gate #else /* !MBCHAR */
7117c478bd9Sstevel@tonic-gate 	/* One byte always represents one tchar.  Easy! */
7127c478bd9Sstevel@tonic-gate 	int	i;
7137c478bd9Sstevel@tonic-gate 	unsigned char	*s;
7147c478bd9Sstevel@tonic-gate 	tchar	*t;
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate #ifdef	DBG
7177c478bd9Sstevel@tonic-gate 	tprintf("Entering write_(d=%d, buf=0x%x, nch=%d);\n",
7187c478bd9Sstevel@tonic-gate 	    d, buf, nch); /* Hope printf() doesn't call write_() itself! */
7197c478bd9Sstevel@tonic-gate #endif /* DBG */
7207c478bd9Sstevel@tonic-gate 	assert(nch <= sizeof (chbuf));
7217c478bd9Sstevel@tonic-gate 	for (i = 0, t = buf, s = chbuf; i < nch; ++i) {
7227c478bd9Sstevel@tonic-gate 	    *s++ = (char)((*t++)&0xff);
7237c478bd9Sstevel@tonic-gate 	}
7247c478bd9Sstevel@tonic-gate 	return (write(d, (char *)chbuf, nch));
7257c478bd9Sstevel@tonic-gate #endif
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate #undef chbuf
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate #include <sys/types.h>
7317c478bd9Sstevel@tonic-gate #include <sys/stat.h>	/* satruct stat */
7327c478bd9Sstevel@tonic-gate #include <dirent.h>	/* DIR */
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate extern DIR *Dirp;
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate int
stat_(tchar * path,struct stat * buf)7377c478bd9Sstevel@tonic-gate stat_(tchar *path, struct stat *buf)
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	tstostr(chbuf, path);
7427c478bd9Sstevel@tonic-gate 	return (stat((char *)chbuf, buf));
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate int
lstat_(tchar * path,struct stat * buf)7467c478bd9Sstevel@tonic-gate lstat_(tchar *path, struct stat *buf)
7477c478bd9Sstevel@tonic-gate {
7487c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	tstostr(chbuf, path);
7517c478bd9Sstevel@tonic-gate 	return (lstat((char *)chbuf, buf));
7527c478bd9Sstevel@tonic-gate }
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate int
chdir_(tchar * path)7557c478bd9Sstevel@tonic-gate chdir_(tchar *path)
7567c478bd9Sstevel@tonic-gate {
7577c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	tstostr(chbuf, path);
7607c478bd9Sstevel@tonic-gate 	return (chdir((char *)chbuf));
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate tchar *
getwd_(tchar * path)7647c478bd9Sstevel@tonic-gate getwd_(tchar *path)
7657c478bd9Sstevel@tonic-gate {
7667c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7677c478bd9Sstevel@tonic-gate 	int	rc;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	rc = (int)getwd((char *)chbuf);
7707c478bd9Sstevel@tonic-gate 	if (rc == 0) {
7717c478bd9Sstevel@tonic-gate 		return (0);
7727c478bd9Sstevel@tonic-gate 	} else {
7737c478bd9Sstevel@tonic-gate 		return (strtots(path, chbuf));
7747c478bd9Sstevel@tonic-gate 	}
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate int
unlink_(tchar * path)7787c478bd9Sstevel@tonic-gate unlink_(tchar *path)
7797c478bd9Sstevel@tonic-gate {
7807c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	tstostr(chbuf, path);
7837c478bd9Sstevel@tonic-gate 	return (unlink((char *)chbuf));
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate DIR *
opendir_(tchar * dirname)7877c478bd9Sstevel@tonic-gate opendir_(tchar *dirname)
7887c478bd9Sstevel@tonic-gate {
7897c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	extern DIR *opendir();
7927c478bd9Sstevel@tonic-gate 	DIR	*dir;
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	dir = opendir(tstostr(chbuf, dirname));
7957c478bd9Sstevel@tonic-gate 	if (dir != NULL) {
7967c478bd9Sstevel@tonic-gate 		setfd(dir->dd_fd);
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate 	return (Dirp = dir);
7997c478bd9Sstevel@tonic-gate }
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate int
closedir_(DIR * dirp)8027c478bd9Sstevel@tonic-gate closedir_(DIR *dirp)
8037c478bd9Sstevel@tonic-gate {
8047c478bd9Sstevel@tonic-gate 	int ret;
8057c478bd9Sstevel@tonic-gate 	extern int closedir();
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	ret = closedir(dirp);
8087c478bd9Sstevel@tonic-gate 	Dirp = NULL;
8097c478bd9Sstevel@tonic-gate 	return (ret);
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate int
gethostname_(tchar * name,int namelen)8137c478bd9Sstevel@tonic-gate gethostname_(tchar *name, int namelen)
8147c478bd9Sstevel@tonic-gate {
8157c478bd9Sstevel@tonic-gate 	char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 	assert(namelen < BUFSIZ);
8187c478bd9Sstevel@tonic-gate 	if (gethostname((char *)chbuf, sizeof (chbuf)) != 0) {
8197c478bd9Sstevel@tonic-gate 		return (-1);
8207c478bd9Sstevel@tonic-gate 	}
8217c478bd9Sstevel@tonic-gate 	if (mbstotcs(name, chbuf, namelen) < 0) {
8227c478bd9Sstevel@tonic-gate 		return (-1);
8237c478bd9Sstevel@tonic-gate 	}
8247c478bd9Sstevel@tonic-gate 	return (0); /* Succeeded. */
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate int
readlink_(tchar * path,tchar * buf,int bufsiz)8287c478bd9Sstevel@tonic-gate readlink_(tchar *path, tchar *buf, int bufsiz)
8297c478bd9Sstevel@tonic-gate {
8307c478bd9Sstevel@tonic-gate 	char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
8317c478bd9Sstevel@tonic-gate 	char	chpath[MAXPATHLEN + 1];
8327c478bd9Sstevel@tonic-gate 	int	i;
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 	tstostr(chpath, path);
8357c478bd9Sstevel@tonic-gate 	i = readlink(chpath, (char *)chbuf, sizeof (chbuf));
8367c478bd9Sstevel@tonic-gate 	if (i < 0) {
8377c478bd9Sstevel@tonic-gate 		return (-1);
8387c478bd9Sstevel@tonic-gate 	}
8397c478bd9Sstevel@tonic-gate 	chbuf[i] = (char)0;	/* readlink() doesn't put NULL. */
8407c478bd9Sstevel@tonic-gate 	i = mbstotcs(buf, chbuf, bufsiz);
8417c478bd9Sstevel@tonic-gate 	if (i < 0) {
8427c478bd9Sstevel@tonic-gate 		return (-1);
8437c478bd9Sstevel@tonic-gate 	}
8447c478bd9Sstevel@tonic-gate 	return (i - 1); /* Return # of tchars EXCLUDING the terminating NULL. */
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate 
84770a587ddSchin /* checks that it's a number */
84870a587ddSchin 
84970a587ddSchin int
chkalldigit_(tchar * str)85070a587ddSchin chkalldigit_(tchar *str)
85170a587ddSchin {
85270a587ddSchin 	char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
85370a587ddSchin 	char *c = chbuf;
85470a587ddSchin 
85570a587ddSchin 	(void) tstostr(chbuf, str);
85670a587ddSchin 
85770a587ddSchin 	while (*c)
85870a587ddSchin 		if (!isdigit(*(c++)))
85970a587ddSchin 			return (-1);
86070a587ddSchin 
86170a587ddSchin 	return (0);
86270a587ddSchin }
86370a587ddSchin 
8647c478bd9Sstevel@tonic-gate int
atoi_(tchar * str)8657c478bd9Sstevel@tonic-gate atoi_(tchar *str)
8667c478bd9Sstevel@tonic-gate {
8677c478bd9Sstevel@tonic-gate 	char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	tstostr(chbuf, str);
8707c478bd9Sstevel@tonic-gate 	return (atoi((char *)chbuf));
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate tchar *
simple(tchar * s)8747c478bd9Sstevel@tonic-gate simple(tchar *s)
8757c478bd9Sstevel@tonic-gate {
8766c02b4a4Smuffin 	tchar *sname = s;
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	while (1) {
8797c478bd9Sstevel@tonic-gate 		if (any('/', sname)) {
8807c478bd9Sstevel@tonic-gate 			while (*sname++ != '/')
8817c478bd9Sstevel@tonic-gate 				;
8827c478bd9Sstevel@tonic-gate 		} else {
8837c478bd9Sstevel@tonic-gate 			return (sname);
8847c478bd9Sstevel@tonic-gate 		}
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate }
887