1 /*
2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
8
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15 /*
16 * This module provides with system/library function substitutes for tchar
17 * datatype. This also includes two conversion functions between tchar and
18 * char arrays.
19 *
20 * T. Kurosaka, Palo Alto, California, USA
21 * March 1989
22 *
23 * Implementation Notes:
24 * Many functions defined here use a "char" buffer chbuf[]. In the
25 * first attempt, there used to be only one chbuf defined as static
26 * (private) variable and shared by these functions. csh linked with that
27 * version of this file misbehaved in interpreting "eval `tset ....`".
28 * (in general, builtin function with back-quoted expression).
29 * This bug seemed to be caused by sharing of chbuf
30 * by these functions simultanously (thru vfork() mechanism?). We could not
31 * identify which two functions interfere each other so we decided to
32 * have each of these function its private instance of chbuf.
33 * The size of chbuf[] might be much bigger than necessary for some functions.
34 */
35 #ifdef DBG
36 #include <stdio.h> /* For <assert.h> needs stderr defined. */
37 #else /* !DBG */
38 #define NDEBUG /* Disable assert(). */
39 #endif /* !DBG */
40
41 #include <assert.h>
42 #include "sh.h"
43
44 #ifdef MBCHAR
45 #include <widec.h> /* For wcsetno() */
46 #endif
47
48 #include <sys/param.h> /* MAXPATHLEN */
49 #include <fcntl.h>
50 #include <unistd.h>
51
52 bool cflg;
53
54 /*
55 * strtots(to, from): convert a char string 'from' into a tchar buffer 'to'.
56 * 'to' is assumed to have the enough size to hold the conversion result.
57 * When 'to' is NOSTR(=(tchar *)0), strtots() attempts to allocate a space
58 * automatically using xalloc(). It is caller's responsibility to
59 * free the space allocated in this way, by calling xfree(ptr).
60 * In either case, strtots() returns the pointer to the conversion
61 * result (i.e. 'to', if 'to' wasn't NOSTR, or the allocated space.).
62 * When a conversion or allocateion failed, NOSTR is returned.
63 */
64
65 tchar *
strtots(tchar * to,char * from)66 strtots(tchar *to, char *from)
67 {
68 int i;
69
70 if (to == NOSTR) { /* Need to xalloc(). */
71 int i;
72
73 i = mbstotcs(NOSTR, from, 0);
74 if (i < 0) {
75 return (NOSTR);
76 }
77
78 /* Allocate space for the resulting tchar array. */
79 to = (tchar *)xalloc(i * sizeof (tchar));
80 }
81 i = mbstotcs(to, from, INT_MAX);
82 if (i < 0) {
83 return (NOSTR);
84 }
85 return (to);
86 }
87
88 char *
tstostr(char * to,tchar * from)89 tstostr(char *to, tchar *from)
90 {
91 tchar *ptc;
92 wchar_t wc;
93 char *pmb;
94 int len;
95
96 if (to == (char *)NULL) { /* Need to xalloc(). */
97 int i;
98 int i1;
99 char junk[MB_LEN_MAX];
100
101 /* Get sum of byte counts for each char in from. */
102 i = 0;
103 ptc = from;
104 while (wc = (wchar_t)((*ptc++)&TRIM)) {
105 if ((i1 = wctomb(junk, wc)) <= 0) {
106 i1 = 1;
107 }
108 i += i1;
109 }
110
111 /* Allocate that much. */
112 to = (char *)xalloc(i + 1);
113 }
114
115 ptc = from;
116 pmb = to;
117 while (wc = (wchar_t)((*ptc++)&TRIM)) {
118 if ((len = wctomb(pmb, wc)) <= 0) {
119 *pmb = (unsigned char)wc;
120 len = 1;
121 }
122 pmb += len;
123 }
124 *pmb = (char)0;
125 return (to);
126 }
127
128 /*
129 * mbstotcs(to, from, tosize) is similar to strtots() except that
130 * this returns # of tchars of the resulting tchar string.
131 * When NULL is give as the destination, no real conversion is carried out,
132 * and the function reports how many tchar characters would be made in
133 * the converted result including the terminating 0.
134 * tchar *to; - Destination buffer, or NULL.
135 * char *from; - Source string.
136 * int tosize; - Size of to, in terms of # of tchars.
137 */
138 int
mbstotcs(tchar * to,char * from,int tosize)139 mbstotcs(tchar *to, char *from, int tosize)
140 {
141 tchar *ptc = to;
142 char *pmb = from;
143 wchar_t wc;
144 int chcnt = 0;
145 int j;
146
147
148 /* Just count how many tchar would be in the result. */
149 if (to == (tchar *)NULL) {
150 while (*pmb) {
151 if ((j = mbtowc(&wc, pmb, MB_CUR_MAX)) <= 0) {
152 j = 1;
153 }
154 pmb += j;
155 chcnt++;
156 }
157 chcnt++; /* For terminator. */
158 return (chcnt); /* # of chars including terminating zero. */
159 } else { /* Do the real conversion. */
160 while (*pmb) {
161 if ((j = mbtowc(&wc, pmb, MB_CUR_MAX)) <= 0) {
162 wc = (unsigned char)*pmb;
163 j = 1;
164 }
165 pmb += j;
166 *(ptc++) = (tchar)wc;
167 if (++chcnt >= tosize) {
168 break;
169 }
170 }
171 /* Terminate with zero only when space is left. */
172 if (chcnt < tosize) {
173 *ptc = (tchar)0;
174 ++chcnt;
175 }
176 return (chcnt); /* # of chars including terminating zero. */
177 }
178 }
179
180
181 /* tchar version of STRING functions. */
182
183 /*
184 * Returns the number of
185 * non-NULL tchar elements in tchar string argument.
186 */
187 int
strlen_(tchar * s)188 strlen_(tchar *s)
189 {
190 int n;
191
192 n = 0;
193 while (*s++) {
194 n++;
195 }
196 return (n);
197 }
198
199 /*
200 * Concatenate tchar string s2 on the end of s1. S1's space must be large
201 * enough. Return s1.
202 */
203 tchar *
strcat_(tchar * s1,tchar * s2)204 strcat_(tchar *s1, tchar *s2)
205 {
206 tchar *os1;
207
208 os1 = s1;
209 while (*s1++)
210 ;
211 --s1;
212 while (*s1++ = *s2++)
213 ;
214 return (os1);
215 }
216
217 /*
218 * Compare tchar strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
219 * BUGS: Comparison between two characters are done by subtracting two chars
220 * after converting each to an unsigned long int value. It might not make
221 * a whole lot of sense to do that if the characters are in represented
222 * as wide characters and the two characters belong to different codesets.
223 * Therefore, this function should be used only to test the equallness.
224 */
225 int
strcmp_(tchar * s1,tchar * s2)226 strcmp_(tchar *s1, tchar *s2)
227 {
228 while (*s1 == *s2++) {
229 if (*s1++ == (tchar)0) {
230 return (0);
231 }
232 }
233 return (((unsigned long)*s1) - ((unsigned long)*(--s2)));
234 }
235
236 /*
237 * This is only used in sh.glob.c for sorting purpose.
238 */
239 int
strcoll_(tchar * s1,tchar * s2)240 strcoll_(tchar *s1, tchar *s2)
241 {
242 char buf1[BUFSIZ];
243 char buf2[BUFSIZ];
244
245 tstostr(buf1, s1);
246 tstostr(buf2, s2);
247 return (strcoll(buf1, buf2));
248 }
249
250 /*
251 * Copy tchar string s2 to s1. s1 must be large enough.
252 * return s1
253 */
254 tchar *
strcpy_(tchar * s1,tchar * s2)255 strcpy_(tchar *s1, tchar *s2)
256 {
257 tchar *os1;
258
259 os1 = s1;
260 while (*s1++ = *s2++)
261 ;
262 return (os1);
263 }
264
265 /*
266 * Return the ptr in sp at which the character c appears;
267 * NULL if not found
268 */
269 tchar *
index_(tchar * sp,tchar c)270 index_(tchar *sp, tchar c)
271 {
272
273 do {
274 if (*sp == c) {
275 return (sp);
276 }
277 } while (*sp++);
278 return (NULL);
279 }
280
281 /*
282 * Return the ptr in sp at which the character c last
283 * appears; NOSTR if not found
284 */
285
286 tchar *
rindex_(tchar * sp,tchar c)287 rindex_(tchar *sp, tchar c)
288 {
289 tchar *r;
290
291 r = NOSTR;
292 do {
293 if (*sp == c) {
294 r = sp;
295 }
296 } while (*sp++);
297 return (r);
298 }
299
300 /* Additional misc functions. */
301
302 /* Calculate the display width of a string. */
303 int
tswidth(tchar * ts)304 tswidth(tchar *ts)
305 {
306 #ifdef MBCHAR
307 wchar_t tc;
308 int w = 0;
309 int p_col;
310
311 while (tc = *ts++) {
312 if ((p_col = wcwidth((wchar_t)tc)) > 0)
313 w += p_col;
314 }
315 return (w);
316 #else /* !MBCHAR --- one char always occupies one column. */
317 return (strlen_(ts));
318 #endif
319 }
320
321 /*
322 * Two getenv() substitute functions. They differ in the type of arguments.
323 * BUGS: Both returns the pointer to an allocated space where the env var's
324 * values is stored. This space is freed automatically on the successive
325 * call of either function. Therefore the caller must copy the contents
326 * if it needs to access two env vars. There is an arbitary limitation
327 * on the number of chars of a env var name.
328 */
329 #define LONGEST_ENVVARNAME 256 /* Too big? */
330 tchar *
getenv_(tchar * name_)331 getenv_(tchar *name_)
332 {
333 char name[LONGEST_ENVVARNAME * MB_LEN_MAX];
334
335 assert(strlen_(name_) < LONGEST_ENVVARNAME);
336 return (getenvs_(tstostr(name, name_)));
337 }
338
339 tchar *
getenvs_(char * name)340 getenvs_(char *name)
341 {
342 static tchar *pbuf = (tchar *)NULL;
343 char *val;
344
345 if (pbuf) {
346 xfree(pbuf);
347 pbuf = NOSTR;
348 }
349 val = getenv(name);
350 if (val == (char *)NULL) {
351 return (NOSTR);
352 }
353 return (pbuf = strtots(NOSTR, val));
354 }
355
356 /* Followings are the system call interface for tchar strings. */
357
358 /*
359 * creat() and open() replacement.
360 * BUGS: An unusually long file name could be dangerous.
361 */
362 int
creat_(tchar * name_,int mode)363 creat_(tchar *name_, int mode)
364 {
365 int fd;
366 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
367
368 tstostr(chbuf, name_);
369 fd = creat((char *)chbuf, mode);
370 if (fd != -1) {
371 setfd(fd);
372 }
373 return (fd);
374 }
375
376 /*VARARGS2*/
377 int
open_(path_,flags,mode)378 open_(path_, flags, mode)
379 tchar *path_;
380 int flags;
381 int mode; /* May be omitted. */
382 {
383 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
384 int fd;
385
386 tstostr(chbuf, path_);
387 fd = open((char *)chbuf, flags, mode);
388 if (fd != -1) {
389 setfd(fd);
390 }
391 return (fd);
392 }
393
394 /*
395 * mkstemp replacement
396 */
397 int
mkstemp_(tchar * name_)398 mkstemp_(tchar *name_)
399 {
400 int fd;
401 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
402
403 tstostr(chbuf, name_);
404 fd = mkstemp((char *)chbuf);
405 if (fd != -1) {
406 setfd(fd);
407 strtots(name_, chbuf);
408 }
409 return (fd);
410 }
411
412 /*
413 * read() and write() reaplacement.
414 * int d;
415 * tchar *buf; - where the result be stored. Not NULL terminated.
416 * int nchreq; - # of tchars requrested.
417 */
418 int
read_(int d,tchar * buf,int nchreq)419 read_(int d, tchar *buf, int nchreq)
420 {
421 unsigned char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
422 #ifdef MBCHAR
423 /*
424 * We would have to read more than tchar bytes
425 * when there are multibyte characters in the file.
426 */
427 int i, j, fflags;
428 unsigned char *s; /* Byte being scanned for a multibyte char. */
429 /* Points to the pos where next read() to read the data into. */
430 unsigned char *p;
431 tchar *t;
432 wchar_t wc;
433 int b_len;
434 int nchread = 0; /* Count how many bytes has been read. */
435 int nbytread = 0; /* Total # of bytes read. */
436 /* # of bytes needed to complete the last char just read. */
437 int delta;
438 unsigned char *q; /* q points to the first invalid byte. */
439 int mb_cur_max = MB_CUR_MAX;
440 #ifdef DBG
441 tprintf("Entering read_(d=%d, buf=0x%x, nchreq=%d);\n",
442 d, buf, nchreq);
443 #endif /* DBG */
444 /*
445 * Step 1: We collect the exact number of bytes that make
446 * nchreq characters into chbuf.
447 * We must be careful not to read too many bytes as we
448 * cannot push back such over-read bytes.
449 * The idea we use here is that n multibyte characters are stored
450 * in no less than n but less than n*MB_CUR_MAX bytes.
451 */
452 assert(nchreq <= BUFSIZ);
453 delta = 0;
454 p = s = chbuf;
455 t = buf;
456 while (nchread < nchreq) {
457 int m; /* # of bytes to try to read this time. */
458 int k; /* # of bytes successfully read. */
459
460 retry:
461 /*
462 * Let's say the (N+1)'th byte bN is actually the first
463 * byte of a three-byte character c.
464 * In that case, p, s, q look like this:
465 *
466 * /-- already read--\ /-- not yet read --\
467 * chbuf[]: b0 b1 ..... bN bN+1 bN+2 bN+2 ...
468 * ^ ^ ^
469 * | | |
470 * p s q
471 * \----------/
472 * c hasn't been completed
473 *
474 * Just after the next read(), p and q will be adavanced to:
475 *
476 * /-- already read-----------------------\ /-- not yet -
477 * chbuf[]: b0 b1 ..... bN bN+1 bN+2 bN+2 ... bX bX+1 bX+2...
478 * ^ ^ ^
479 * | | |
480 * s p q
481 * \----------/
482 * c has been completed
483 * but hasn't been scanned
484 */
485 m = nchreq - nchread;
486 assert(p + m < chbuf + sizeof (chbuf));
487 k = read(d, p, m);
488 /*
489 * when child sets O_NDELAY or O_NONBLOCK on stdin
490 * and exits and we are interactive then turn the modes off
491 * and retry
492 */
493 if (k == 0) {
494 if ((intty && !onelflg && !cflg) &&
495 ((fflags = fcntl(d, F_GETFL, 0)) & O_NDELAY)) {
496 fflags &= ~O_NDELAY;
497 fcntl(d, F_SETFL, fflags);
498 goto retry;
499 }
500 } else if (k < 0) {
501 if (errno == EAGAIN) {
502 fflags = fcntl(d, F_GETFL, 0);
503 fflags &= ~O_NONBLOCK;
504 fcntl(d, F_SETFL, fflags);
505 goto retry;
506 }
507 return (-1);
508 }
509 nbytread += k;
510 q = p + k;
511 delta = 0;
512
513 /* Try scaning characters in s..q-1 */
514 while (s < q) {
515 /* Convert the collected bytes into tchar array. */
516 if (*s == 0) {
517 /* NUL is treated as a normal char here. */
518 *t++ = 0;
519 s++;
520 nchread++;
521 continue;
522 }
523
524 if ((b_len = q - s) > mb_cur_max) {
525 b_len = mb_cur_max;
526 }
527 if ((j = mbtowc(&wc, (char *)s, b_len)) <= 0) {
528 if (mb_cur_max > 1 && b_len < mb_cur_max) {
529 /*
530 * Needs more byte to complete this char
531 * In order to read() more than delta
532 * bytes.
533 */
534 break;
535 }
536 wc = (unsigned char)*s;
537 j = 1;
538 }
539
540 *t++ = wc;
541 nchread++;
542 s += j;
543 }
544
545 if (k < m) {
546 /* We've read as many bytes as possible. */
547 while (s < q) {
548 if ((b_len = q - s) > mb_cur_max) {
549 b_len = mb_cur_max;
550 }
551 if ((j = mbtowc(&wc, (char *)s, b_len)) <= 0) {
552 wc = (unsigned char)*s;
553 j = 1;
554 }
555 *t++ = wc;
556 nchread++;
557 s += j;
558 }
559 return (nchread);
560 }
561
562 p = q;
563 }
564
565 if (mb_cur_max == 1 || (delta = q - s) == 0) {
566 return (nchread);
567 }
568
569 /*
570 * We may have (MB_CUR_MAX - 1) unread data in the buffer.
571 * Here, the last converted data was an illegal character which was
572 * treated as one byte character. We don't know at this point
573 * whether or not the remaining data is in legal sequence.
574 * We first attempt to convert the remaining data.
575 */
576 do {
577 if ((j = mbtowc(&wc, (char *)s, delta)) <= 0)
578 break;
579 *t++ = wc;
580 nchread++;
581 s += j;
582 delta -= j;
583 } while (delta > 0);
584
585 if (delta == 0)
586 return (nchread);
587
588 /*
589 * There seem to be ugly sequence in the buffer. Fill up till
590 * mb_cur_max and see if we can get a right sequence.
591 */
592 while (delta < mb_cur_max) {
593 assert((q + 1) < (chbuf + sizeof (chbuf)));
594 if (read(d, q, 1) != 1)
595 break;
596 delta++;
597 q++;
598 if (mbtowc(&wc, (char *)s, delta) > 0) {
599 *t = wc;
600 return (nchread + 1);
601 }
602 }
603
604 /*
605 * no luck. we have filled MB_CUR_MAX bytes in the buffer.
606 * Ideally we should return with leaving such data off and
607 * put them into a local buffer for next read, but we don't
608 * have such.
609 * So, stop reading further, and treat them as all single
610 * byte characters.
611 */
612 while (s < q) {
613 b_len = q - s;
614 if ((j = mbtowc(&wc, (char *)s, b_len)) <= 0) {
615 wc = (unsigned char)*s;
616 j = 1;
617 }
618 *t++ = wc;
619 nchread++;
620 s += j;
621 }
622 return (nchread);
623
624 #else /* !MBCHAR */
625 /* One byte always represents one tchar. Easy! */
626 int i;
627 unsigned char *s;
628 tchar *t;
629 int nchread;
630
631 #ifdef DBG
632 tprintf("Entering read_(d=%d, buf=0x%x, nchreq=%d);\n",
633 d, buf, nchreq);
634 #endif /* DBG */
635 assert(nchreq <= BUFSIZ);
636 retry:
637 nchread = read(d, (char *)chbuf, nchreq);
638 /*
639 * when child sets O_NDELAY or O_NONBLOCK on stdin
640 * and exits and we are interactive then turn the modes off
641 * and retry
642 */
643 if (nchread == 0) {
644 if ((intty && !onelflg && !cflg) &&
645 ((fflags = fcntl(d, F_GETFL, 0)) & O_NDELAY)) {
646 fflags &= ~O_NDELAY;
647 fcntl(d, F_SETFL, fflags);
648 goto retry;
649 }
650 } else if (nchread < 0) {
651 if (errno == EAGAIN) {
652 fflags = fcntl(d, F_GETFL, 0);
653 fflags &= ~O_NONBLOCK;
654 fcntl(d, F_SETFL, fflags);
655 goto retry;
656 }
657 len = 0;
658 } else {
659 for (i = 0, t = buf, s = chbuf; i < nchread; ++i) {
660 *t++ = ((tchar)*s++);
661 }
662 }
663 return (nchread);
664 #endif
665 }
666
667 /*
668 * BUG: write_() returns -1 on failure, or # of BYTEs it has written.
669 * For consistency and symmetry, it should return the number of
670 * characters it has actually written, but that is technically
671 * difficult although not impossible. Anyway, the return
672 * value of write() has never been used by the original csh,
673 * so this bug should be OK.
674 */
675 int
write_(int d,tchar * buf,int nch)676 write_(int d, tchar *buf, int nch)
677 {
678 unsigned char chbuf[BUFSIZ*MB_LEN_MAX]; /* General use buffer. */
679 #ifdef MBCHAR
680 tchar *pt;
681 unsigned char *pc;
682 wchar_t wc;
683 int i, j;
684
685 #ifdef DBG
686 tprintf("Entering write_(d=%d, buf=0x%x, nch=%d);\n",
687 d, buf, nch); /* Hope printf() doesn't call write_() itself! */
688 #endif /* DBG */
689 assert(nch * MB_CUR_MAX < sizeof (chbuf));
690 i = nch;
691 pt = buf;
692 pc = chbuf;
693 while (i--) {
694 /*
695 * Convert to tchar string.
696 * NUL is treated as normal char here.
697 */
698 wc = (wchar_t)((*pt++)&TRIM);
699 if (wc == (wchar_t)0) {
700 *pc++ = 0;
701 } else {
702 if ((j = wctomb((char *)pc, wc)) <= 0) {
703 *pc = (unsigned char)wc;
704 j = 1;
705 }
706 pc += j;
707 }
708 }
709 return (write(d, chbuf, pc - chbuf));
710 #else /* !MBCHAR */
711 /* One byte always represents one tchar. Easy! */
712 int i;
713 unsigned char *s;
714 tchar *t;
715
716 #ifdef DBG
717 tprintf("Entering write_(d=%d, buf=0x%x, nch=%d);\n",
718 d, buf, nch); /* Hope printf() doesn't call write_() itself! */
719 #endif /* DBG */
720 assert(nch <= sizeof (chbuf));
721 for (i = 0, t = buf, s = chbuf; i < nch; ++i) {
722 *s++ = (char)((*t++)&0xff);
723 }
724 return (write(d, (char *)chbuf, nch));
725 #endif
726 }
727
728 #undef chbuf
729
730 #include <sys/types.h>
731 #include <sys/stat.h> /* satruct stat */
732 #include <dirent.h> /* DIR */
733
734 extern DIR *Dirp;
735
736 int
stat_(tchar * path,struct stat * buf)737 stat_(tchar *path, struct stat *buf)
738 {
739 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
740
741 tstostr(chbuf, path);
742 return (stat((char *)chbuf, buf));
743 }
744
745 int
lstat_(tchar * path,struct stat * buf)746 lstat_(tchar *path, struct stat *buf)
747 {
748 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
749
750 tstostr(chbuf, path);
751 return (lstat((char *)chbuf, buf));
752 }
753
754 int
chdir_(tchar * path)755 chdir_(tchar *path)
756 {
757 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
758
759 tstostr(chbuf, path);
760 return (chdir((char *)chbuf));
761 }
762
763 tchar *
getwd_(tchar * path)764 getwd_(tchar *path)
765 {
766 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
767 int rc;
768
769 rc = (int)getwd((char *)chbuf);
770 if (rc == 0) {
771 return (0);
772 } else {
773 return (strtots(path, chbuf));
774 }
775 }
776
777 int
unlink_(tchar * path)778 unlink_(tchar *path)
779 {
780 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
781
782 tstostr(chbuf, path);
783 return (unlink((char *)chbuf));
784 }
785
786 DIR *
opendir_(tchar * dirname)787 opendir_(tchar *dirname)
788 {
789 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
790
791 extern DIR *opendir();
792 DIR *dir;
793
794 dir = opendir(tstostr(chbuf, dirname));
795 if (dir != NULL) {
796 setfd(dir->dd_fd);
797 }
798 return (Dirp = dir);
799 }
800
801 int
closedir_(DIR * dirp)802 closedir_(DIR *dirp)
803 {
804 int ret;
805 extern int closedir();
806
807 ret = closedir(dirp);
808 Dirp = NULL;
809 return (ret);
810 }
811
812 int
gethostname_(tchar * name,int namelen)813 gethostname_(tchar *name, int namelen)
814 {
815 char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
816
817 assert(namelen < BUFSIZ);
818 if (gethostname((char *)chbuf, sizeof (chbuf)) != 0) {
819 return (-1);
820 }
821 if (mbstotcs(name, chbuf, namelen) < 0) {
822 return (-1);
823 }
824 return (0); /* Succeeded. */
825 }
826
827 int
readlink_(tchar * path,tchar * buf,int bufsiz)828 readlink_(tchar *path, tchar *buf, int bufsiz)
829 {
830 char chbuf[MAXPATHLEN * MB_LEN_MAX]; /* General use buffer. */
831 char chpath[MAXPATHLEN + 1];
832 int i;
833
834 tstostr(chpath, path);
835 i = readlink(chpath, (char *)chbuf, sizeof (chbuf));
836 if (i < 0) {
837 return (-1);
838 }
839 chbuf[i] = (char)0; /* readlink() doesn't put NULL. */
840 i = mbstotcs(buf, chbuf, bufsiz);
841 if (i < 0) {
842 return (-1);
843 }
844 return (i - 1); /* Return # of tchars EXCLUDING the terminating NULL. */
845 }
846
847 /* checks that it's a number */
848
849 int
chkalldigit_(tchar * str)850 chkalldigit_(tchar *str)
851 {
852 char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
853 char *c = chbuf;
854
855 (void) tstostr(chbuf, str);
856
857 while (*c)
858 if (!isdigit(*(c++)))
859 return (-1);
860
861 return (0);
862 }
863
864 int
atoi_(tchar * str)865 atoi_(tchar *str)
866 {
867 char chbuf[BUFSIZ * MB_LEN_MAX]; /* General use buffer. */
868
869 tstostr(chbuf, str);
870 return (atoi((char *)chbuf));
871 }
872
873 tchar *
simple(tchar * s)874 simple(tchar *s)
875 {
876 tchar *sname = s;
877
878 while (1) {
879 if (any('/', sname)) {
880 while (*sname++ != '/')
881 ;
882 } else {
883 return (sname);
884 }
885 }
886 }
887