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