1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 support.c - Define missing function
21 Written by Masanao Izumo <mo@goice.co.jp>
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif /* HAVE_CONFIG_H */
27
28 #ifdef __POCC__
29 #include <sys/types.h>
30 #endif /* for off_t */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif /* HAVE_UNISTD_H */
36 #include <stdarg.h>
37 #ifdef HAVE_SYS_TIME_H
38 #include <sys/time.h>
39 #endif /* HAVE_SYS_TIME_H */
40 #ifdef HAVE_SYS_TYPES_H
41 #include <sys/types.h>
42 #endif /* HAVE_SYS_TYPES_H */
43 #ifndef NO_STRING_H
44 #include <string.h>
45 #else
46 #include <strings.h>
47 #endif
48 #ifdef __W32__
49 #include <windows.h>
50 #endif /* __W32__ */
51
52 #ifdef HAVE_SYS_PARAM_H
53 #include <sys/param.h>
54 #endif /* HAVE_SYS_PARAM_H */
55 #include <ctype.h>
56
57 #include "timidity.h"
58 #include "common.h"
59 #include "mblock.h"
60 #ifdef __MACOS__
61 #include <Threads.h>
62 #endif
63
64 #ifndef HAVE_VSNPRINTF
65 /* From glib-1.1.13:gstrfuncs.c
66 * Modified by Masanao Izumo <mo@goice.co.jp>
67 */
68 #ifndef VA_COPY
69 # if (defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (__WIN32__))) || defined (__WATCOMC__)
70 # define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
71 # elif defined (VA_COPY_AS_ARRAY)
72 # define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
73 # else /* va_list is a pointer */
74 # define VA_COPY(ap1, ap2) ((ap1) = (ap2))
75 # endif /* va_list is a pointer */
76 #endif /* !VA_COPY */
77
printf_string_upper_bound(const char * format,va_list args)78 static int printf_string_upper_bound (const char* format,
79 va_list args)
80 {
81 int len = 1;
82
83 while (*format)
84 {
85 int long_int = 0;
86 int extra_long = 0;
87 char c;
88
89 c = *format++;
90
91 if (c == '%')
92 {
93 int done = 0;
94
95 while (*format && !done)
96 {
97 switch (*format++)
98 {
99 char *string_arg;
100
101 case '*':
102 len += va_arg (args, int);
103 break;
104 case '1':
105 case '2':
106 case '3':
107 case '4':
108 case '5':
109 case '6':
110 case '7':
111 case '8':
112 case '9':
113 /* add specified format length, since it might exceed the
114 * size we assume it to have.
115 */
116 format -= 1;
117 len += strtol (format, (char**) &format, 10);
118 break;
119 case 'h':
120 /* ignore short int flag, since all args have at least the
121 * same size as an int
122 */
123 break;
124 case 'l':
125 if (long_int)
126 extra_long = 1; /* linux specific */
127 else
128 long_int = 1;
129 break;
130 case 'q':
131 case 'L':
132 long_int = 1;
133 extra_long = 1;
134 break;
135 case 's':
136 string_arg = va_arg (args, char *);
137 if (string_arg)
138 len += strlen (string_arg);
139 else
140 {
141 /* add enough padding to hold "(null)" identifier */
142 len += 16;
143 }
144 done = 1;
145 break;
146 case 'd':
147 case 'i':
148 case 'o':
149 case 'u':
150 case 'x':
151 case 'X':
152 #ifdef G_HAVE_GINT64
153 if (extra_long)
154 (void) va_arg (args, gint64);
155 else
156 #endif /* G_HAVE_GINT64 */
157 {
158 if (long_int)
159 (void) va_arg (args, long);
160 else
161 (void) va_arg (args, int);
162 }
163 len += extra_long ? 64 : 32;
164 done = 1;
165 break;
166 case 'D':
167 case 'O':
168 case 'U':
169 (void) va_arg (args, long);
170 len += 32;
171 done = 1;
172 break;
173 case 'e':
174 case 'E':
175 case 'f':
176 case 'g':
177 #ifdef HAVE_LONG_DOUBLE
178 if (extra_long)
179 (void) va_arg (args, long double);
180 else
181 #endif /* HAVE_LONG_DOUBLE */
182 (void) va_arg (args, double);
183 len += extra_long ? 64 : 32;
184 done = 1;
185 break;
186 case 'c':
187 (void) va_arg (args, int);
188 len += 1;
189 done = 1;
190 break;
191 case 'p':
192 case 'n':
193 (void) va_arg (args, void*);
194 len += 32;
195 done = 1;
196 break;
197 case '%':
198 len += 1;
199 done = 1;
200 break;
201 default:
202 /* ignore unknow/invalid flags */
203 break;
204 }
205 }
206 }
207 else
208 len += 1;
209 }
210
211 return len;
212 }
213
vsnprintf(char * buff,size_t bufsiz,const char * fmt,va_list ap)214 int vsnprintf(char *buff, size_t bufsiz, const char *fmt, va_list ap)
215 {
216 MBlockList pool;
217 char *tmpbuf = buff;
218 int ret;
219 va_list ap2;
220
221 VA_COPY(ap2, ap);
222 init_mblock(&pool);
223 tmpbuf = new_segment(&pool, printf_string_upper_bound(fmt, ap));
224 ret = vsprintf(tmpbuf, fmt, ap2);
225 strncpy(buff, tmpbuf, bufsiz);
226 buff[bufsiz-1] = '\0';
227 reuse_mblock(&pool);
228 va_end(ap2);
229 return ret;
230 }
231 #endif /* HAVE_VSNPRINTF */
232
233
234 #ifndef HAVE_SNPRINTF
snprintf(char * buff,size_t bufsiz,const char * fmt,...)235 int snprintf(char *buff, size_t bufsiz, const char *fmt, ...)
236 {
237 int ret;
238 va_list ap;
239
240 va_start(ap, fmt);
241 ret = vsnprintf(buff, bufsiz, fmt, ap);
242 va_end(ap);
243 return ret;
244 }
245 #endif /* HAVE_SNPRINTF */
246
247 #ifndef HAVE_STRERROR
248 #ifndef HAVE_ERRNO_H
strerror(int errnum)249 char *strerror(int errnum) {
250 static char s[32];
251 sprintf(s, "ERROR %d", errnum);
252 return s;
253 }
254 #else
255
strerror(int errnum)256 char *strerror(int errnum)
257 {
258 int i;
259 static char s[32];
260 struct {
261 int id;
262 char *str;
263 } error_list[] = {
264 #ifdef EPERM
265 {EPERM, "Not super-user"},
266 #endif /* EPERM */
267 #ifdef ENOENT
268 {ENOENT, "No such file or directory"},
269 #endif /* ENOENT */
270 #ifdef ESRCH
271 {ESRCH, "No such process"},
272 #endif /* ESRCH */
273 #ifdef EINTR
274 {EINTR, "interrupted system call"},
275 #endif /* EINTR */
276 #ifdef EIO
277 {EIO, "I/O error"},
278 #endif /* EIO */
279 #ifdef ENXIO
280 {ENXIO, "No such device or address"},
281 #endif /* ENXIO */
282 #ifdef E2BIG
283 {E2BIG, "Arg list too long"},
284 #endif /* E2BIG */
285 #ifdef ENOEXEC
286 {ENOEXEC, "Exec format error"},
287 #endif /* ENOEXEC */
288 #ifdef EBADF
289 {EBADF, "Bad file number"},
290 #endif /* EBADF */
291 #ifdef ECHILD
292 {ECHILD, "No children"},
293 #endif /* ECHILD */
294 #ifdef EAGAIN
295 {EAGAIN, "Resource temporarily unavailable"},
296 #endif /* EAGAIN */
297 #ifdef EWOULDBLOCK
298 {EWOULDBLOCK, "Resource temporarily unavailable"},
299 #endif /* EWOULDBLOCK */
300 #ifdef ENOMEM
301 {ENOMEM, "Not enough core"},
302 #endif /* ENOMEM */
303 #ifdef EACCES
304 {EACCES, "Permission denied"},
305 #endif /* EACCES */
306 #ifdef EFAULT
307 {EFAULT, "Bad address"},
308 #endif /* EFAULT */
309 #ifdef ENOTBLK
310 {ENOTBLK, "Block device required"},
311 #endif /* ENOTBLK */
312 #ifdef EBUSY
313 {EBUSY, "Mount device busy"},
314 #endif /* EBUSY */
315 #ifdef EEXIST
316 {EEXIST, "File exists"},
317 #endif /* EEXIST */
318 #ifdef EXDEV
319 {EXDEV, "Cross-device link"},
320 #endif /* EXDEV */
321 #ifdef ENODEV
322 {ENODEV, "No such device"},
323 #endif /* ENODEV */
324 #ifdef ENOTDIR
325 {ENOTDIR, "Not a directory"},
326 #endif /* ENOTDIR */
327 #ifdef EISDIR
328 {EISDIR, "Is a directory"},
329 #endif /* EISDIR */
330 #ifdef EINVAL
331 {EINVAL, "Invalid argument"},
332 #endif /* EINVAL */
333 #ifdef ENFILE
334 {ENFILE, "File table overflow"},
335 #endif /* ENFILE */
336 #ifdef EMFILE
337 {EMFILE, "Too many open files"},
338 #endif /* EMFILE */
339 #ifdef ENOTTY
340 {ENOTTY, "Inappropriate ioctl for device"},
341 #endif /* ENOTTY */
342 #ifdef ETXTBSY
343 {ETXTBSY, "Text file busy"},
344 #endif /* ETXTBSY */
345 #ifdef EFBIG
346 {EFBIG, "File too large"},
347 #endif /* EFBIG */
348 #ifdef ENOSPC
349 {ENOSPC, "No space left on device"},
350 #endif /* ENOSPC */
351 #ifdef ESPIPE
352 {ESPIPE, "Illegal seek"},
353 #endif /* ESPIPE */
354 #ifdef EROFS
355 {EROFS, "Read only file system"},
356 #endif /* EROFS */
357 #ifdef EMLINK
358 {EMLINK, "Too many links"},
359 #endif /* EMLINK */
360 #ifdef EPIPE
361 {EPIPE, "Broken pipe"},
362 #endif /* EPIPE */
363 #ifdef EDOM
364 {EDOM, "Math arg out of domain of func"},
365 #endif /* EDOM */
366 #ifdef ERANGE
367 {ERANGE, "Math result not representable"},
368 #endif /* ERANGE */
369 #ifdef ENOMSG
370 {ENOMSG, "No message of desired type"},
371 #endif /* ENOMSG */
372 #ifdef EIDRM
373 {EIDRM, "Identifier removed"},
374 #endif /* EIDRM */
375 #ifdef ECHRNG
376 {ECHRNG, "Channel number out of range"},
377 #endif /* ECHRNG */
378 #ifdef EL2NSYNC
379 {EL2NSYNC, "Level 2 not synchronized"},
380 #endif /* EL2NSYNC */
381 #ifdef EL3HLT
382 {EL3HLT, "Level 3 halted"},
383 #endif /* EL3HLT */
384 #ifdef EL3RST
385 {EL3RST, "Level 3 reset"},
386 #endif /* EL3RST */
387 #ifdef ELNRNG
388 {ELNRNG, "Link number out of range"},
389 #endif /* ELNRNG */
390 #ifdef EUNATCH
391 {EUNATCH, "Protocol driver not attached"},
392 #endif /* EUNATCH */
393 #ifdef ENOCSI
394 {ENOCSI, "No CSI structure available"},
395 #endif /* ENOCSI */
396 #ifdef EL2HLT
397 {EL2HLT, "Level 2 halted"},
398 #endif /* EL2HLT */
399 #ifdef EDEADLK
400 {EDEADLK, "Deadlock condition."},
401 #endif /* EDEADLK */
402 #ifdef ENOLCK
403 {ENOLCK, "No record locks available."},
404 #endif /* ENOLCK */
405 #ifdef ECANCELED
406 {ECANCELED, "Operation canceled"},
407 #endif /* ECANCELED */
408 #ifdef ENOTSUP
409 {ENOTSUP, "Operation not supported"},
410 #endif /* ENOTSUP */
411 #ifdef EDQUOT
412 {EDQUOT, "Disc quota exceeded"},
413 #endif /* EDQUOT */
414 #ifdef EBADE
415 {EBADE, "invalid exchange"},
416 #endif /* EBADE */
417 #ifdef EBADR
418 {EBADR, "invalid request descriptor"},
419 #endif /* EBADR */
420 #ifdef EXFULL
421 {EXFULL, "exchange full"},
422 #endif /* EXFULL */
423 #ifdef ENOANO
424 {ENOANO, "no anode"},
425 #endif /* ENOANO */
426 #ifdef EBADRQC
427 {EBADRQC, "invalid request code"},
428 #endif /* EBADRQC */
429 #ifdef EBADSLT
430 {EBADSLT, "invalid slot"},
431 #endif /* EBADSLT */
432 #ifdef EDEADLOCK
433 {EDEADLOCK, "file locking deadlock error"},
434 #endif /* EDEADLOCK */
435 #ifdef EBFONT
436 {EBFONT, "bad font file fmt"},
437 #endif /* EBFONT */
438 #ifdef ENOSTR
439 {ENOSTR, "Device not a stream"},
440 #endif /* ENOSTR */
441 #ifdef ENODATA
442 {ENODATA, "no data (for no delay io)"},
443 #endif /* ENODATA */
444 #ifdef ETIME
445 {ETIME, "timer expired"},
446 #endif /* ETIME */
447 #ifdef ENOSR
448 {ENOSR, "out of streams resources"},
449 #endif /* ENOSR */
450 #ifdef ENONET
451 {ENONET, "Machine is not on the network"},
452 #endif /* ENONET */
453 #ifdef ENOPKG
454 {ENOPKG, "Package not installed"},
455 #endif /* ENOPKG */
456 #ifdef EREMOTE
457 {EREMOTE, "The object is remote"},
458 #endif /* EREMOTE */
459 #ifdef ENOLINK
460 {ENOLINK, "the link has been severed"},
461 #endif /* ENOLINK */
462 #ifdef EADV
463 {EADV, "advertise error"},
464 #endif /* EADV */
465 #ifdef ESRMNT
466 {ESRMNT, "srmount error"},
467 #endif /* ESRMNT */
468 #ifdef ECOMM
469 {ECOMM, "Communication error on send"},
470 #endif /* ECOMM */
471 #ifdef EPROTO
472 {EPROTO, "Protocol error"},
473 #endif /* EPROTO */
474 #ifdef EMULTIHOP
475 {EMULTIHOP, "multihop attempted"},
476 #endif /* EMULTIHOP */
477 #ifdef EBADMSG
478 {EBADMSG, "trying to read unreadable message"},
479 #endif /* EBADMSG */
480 #ifdef ENAMETOOLONG
481 {ENAMETOOLONG, "path name is too long"},
482 #endif /* ENAMETOOLONG */
483 #ifdef EOVERFLOW
484 {EOVERFLOW, "value too large to be stored in data type"},
485 #endif /* EOVERFLOW */
486 #ifdef ENOTUNIQ
487 {ENOTUNIQ, "given log. name not unique"},
488 #endif /* ENOTUNIQ */
489 #ifdef EBADFD
490 {EBADFD, "f.d. invalid for this operation"},
491 #endif /* EBADFD */
492 #ifdef EREMCHG
493 {EREMCHG, "Remote address changed"},
494 #endif /* EREMCHG */
495 #ifdef ELIBACC
496 {ELIBACC, "Can't access a needed shared lib."},
497 #endif /* ELIBACC */
498 #ifdef ELIBBAD
499 {ELIBBAD, "Accessing a corrupted shared lib."},
500 #endif /* ELIBBAD */
501 #ifdef ELIBSCN
502 {ELIBSCN, ".lib section in a.out corrupted."},
503 #endif /* ELIBSCN */
504 #ifdef ELIBMAX
505 {ELIBMAX, "Attempting to link in too many libs."},
506 #endif /* ELIBMAX */
507 #ifdef ELIBEXEC
508 {ELIBEXEC, "Attempting to exec a shared library."},
509 #endif /* ELIBEXEC */
510 #ifdef EILSEQ
511 {EILSEQ, "Illegal byte sequence."},
512 #endif /* EILSEQ */
513 #ifdef ENOSYS
514 {ENOSYS, "Unsupported file system operation"},
515 #endif /* ENOSYS */
516 #ifdef ELOOP
517 {ELOOP, "Symbolic link loop"},
518 #endif /* ELOOP */
519 #ifdef ERESTART
520 {ERESTART, "Restartable system call"},
521 #endif /* ERESTART */
522 #ifdef ESTRPIPE
523 {ESTRPIPE, "if pipe/FIFO, don't sleep in stream head"},
524 #endif /* ESTRPIPE */
525 #ifdef ENOTEMPTY
526 {ENOTEMPTY, "directory not empty"},
527 #endif /* ENOTEMPTY */
528 #ifdef EUSERS
529 {EUSERS, "Too many users (for UFS)"},
530 #endif /* EUSERS */
531 #ifdef ENOTSOCK
532 {ENOTSOCK, "Socket operation on non-socket"},
533 #endif /* ENOTSOCK */
534 #ifdef EDESTADDRREQ
535 {EDESTADDRREQ, "Destination address required"},
536 #endif /* EDESTADDRREQ */
537 #ifdef EMSGSIZE
538 {EMSGSIZE, "Message too long"},
539 #endif /* EMSGSIZE */
540 #ifdef EPROTOTYPE
541 {EPROTOTYPE, "Protocol wrong type for socket"},
542 #endif /* EPROTOTYPE */
543 #ifdef ENOPROTOOPT
544 {ENOPROTOOPT, "Protocol not available"},
545 #endif /* ENOPROTOOPT */
546 #ifdef EPROTONOSUPPORT
547 {EPROTONOSUPPORT, "Protocol not supported"},
548 #endif /* EPROTONOSUPPORT */
549 #ifdef ESOCKTNOSUPPORT
550 {ESOCKTNOSUPPORT, "Socket type not supported"},
551 #endif /* ESOCKTNOSUPPORT */
552 #ifdef EOPNOTSUPP
553 {EOPNOTSUPP, "Operation not supported on socket"},
554 #endif /* EOPNOTSUPP */
555 #ifdef EPFNOSUPPORT
556 {EPFNOSUPPORT, "Protocol family not supported"},
557 #endif /* EPFNOSUPPORT */
558 #ifdef EAFNOSUPPORT
559 {EAFNOSUPPORT, "Address family not supported by"},
560 #endif /* EAFNOSUPPORT */
561 #ifdef EADDRINUSE
562 {EADDRINUSE, "Address already in use"},
563 #endif /* EADDRINUSE */
564 #ifdef EADDRNOTAVAIL
565 {EADDRNOTAVAIL, "Can't assign requested address"},
566 #endif /* EADDRNOTAVAIL */
567 #ifdef ENETDOWN
568 {ENETDOWN, "Network is down"},
569 #endif /* ENETDOWN */
570 #ifdef ENETUNREACH
571 {ENETUNREACH, "Network is unreachable"},
572 #endif /* ENETUNREACH */
573 #ifdef ENETRESET
574 {ENETRESET, "Network dropped connection because"},
575 #endif /* ENETRESET */
576 #ifdef ECONNABORTED
577 {ECONNABORTED, "Software caused connection abort"},
578 #endif /* ECONNABORTED */
579 #ifdef ECONNRESET
580 {ECONNRESET, "Connection reset by peer"},
581 #endif /* ECONNRESET */
582 #ifdef ENOBUFS
583 {ENOBUFS, "No buffer space available"},
584 #endif /* ENOBUFS */
585 #ifdef EISCONN
586 {EISCONN, "Socket is already connected"},
587 #endif /* EISCONN */
588 #ifdef ENOTCONN
589 {ENOTCONN, "Socket is not connected"},
590 #endif /* ENOTCONN */
591 #ifdef ESHUTDOWN
592 {ESHUTDOWN, "Can't send after socket shutdown"},
593 #endif /* ESHUTDOWN */
594 #ifdef ETOOMANYREFS
595 {ETOOMANYREFS, "Too many references: can't splice"},
596 #endif /* ETOOMANYREFS */
597 #ifdef ETIMEDOUT
598 {ETIMEDOUT, "Connection timed out"},
599 #endif /* ETIMEDOUT */
600 #ifdef ECONNREFUSED
601 {ECONNREFUSED, "Connection refused"},
602 #endif /* ECONNREFUSED */
603 #ifdef EHOSTDOWN
604 {EHOSTDOWN, "Host is down"},
605 #endif /* EHOSTDOWN */
606 #ifdef EHOSTUNREACH
607 {EHOSTUNREACH, "No route to host"},
608 #endif /* EHOSTUNREACH */
609 #ifdef EALREADY
610 {EALREADY, "operation already in progress"},
611 #endif /* EALREADY */
612 #ifdef EINPROGRESS
613 {EINPROGRESS, "operation now in progress"},
614 #endif /* EINPROGRESS */
615 #ifdef ESTALE
616 {ESTALE, "Stale NFS file handle"},
617 #endif /* ESTALE */
618 {0, NULL}};
619
620 for(i = 0; error_list[i].str != NULL; i++)
621 if(error_list[i].id == errnum)
622 return error_list[i].str;
623 sprintf(s, "ERROR %d", errnum);
624 return s;
625 }
626 #endif /* HAVE_ERRNO_H */
627 #endif /* HAVE_STRERROR */
628
629 #ifndef HAVE_USLEEP
630 #ifdef __W32__
usleep(unsigned int usec)631 int usleep(unsigned int usec)
632 {
633 Sleep(usec / 1000);
634 return 0;
635 }
636 #elif __MACOS__
usleep(unsigned int)637 int usleep(unsigned int /*usec*/)
638 {
639 YieldToAnyThread();
640 return 0;
641 }
642 #else
usleep(unsigned int usec)643 int usleep(unsigned int usec)
644 {
645 struct timeval tv;
646 tv.tv_sec = usec / 1000000;
647 tv.tv_usec = usec % 1000000;
648 select(0, NULL, NULL, NULL, &tv);
649 return 0;
650 }
651 #endif /* __W32__ */
652 #endif /* HAVE_USLEEP */
653
654 #ifndef HAVE_STRDUP
strdup(const char * s)655 char *strdup(const char *s)
656 {
657 size_t len;
658 char *p;
659
660 len = strlen(s);
661 if((p = (char *)safe_malloc(len + 1)) == NULL)
662 return NULL;
663 return strcpy(p, s);
664 }
665 #endif /* HAVE_STRDUP */
666
667
668 #ifndef HAVE_GETCWD
669 #ifndef MAXPATHLEN
670 #define MAXPATHLEN 1024 /* It must be defined in <sys/param.h> */
671 #endif /* MAXPATHLEN */
672
getcwd(char * buf,size_t size)673 char *getcwd(char *buf, size_t size)
674 {
675 char path[MAXPATHLEN+1];
676 if(getwd(path) == NULL)
677 strcpy(path, ".");
678 if(buf != NULL)
679 return strncpy(buf, path, size);
680 return safe_strdup(path);
681 }
682 #endif /* HAVE_GETCWD */
683
684
685 #ifndef HAVE_STRNCASECMP
strncasecmp(char * s1,char * s2,unsigned int len)686 int strncasecmp(char *s1, char *s2, unsigned int len) {
687 int dif;
688 while (len-- > 0) {
689 if ((dif =
690 (unsigned char)tolower(*s1) - (unsigned char)tolower(*s2++)) != 0)
691 return(dif);
692 if (*s1++ == '\0')
693 break;
694 }
695 return (0);
696 }
697 #endif /* HAVE_STRNCASECMP */
698
699 #ifndef HAVE_SYS_STAT_H
700 #ifdef __MACOS__
stat(const char * filename,struct stat * st)701 int stat(const char *filename, struct stat *st)
702 {
703 Str255 pfilename;
704 CInfoPBRec pb;
705 FSSpec fss;
706
707 c2pstrcpy(pfilename, filename);
708 if (FSMakeFSSpec(0, 0, pfilename, &fss) == noErr)
709 {
710 pb.hFileInfo.ioNamePtr = fss.name;
711 pb.hFileInfo.ioVRefNum = fss.vRefNum;
712 pb.hFileInfo.ioFDirIndex = 0;
713 pb.hFileInfo.ioDirID = fss.parID;
714 if (PBGetCatInfoSync(&pb) == noErr)
715 {
716 st->st_mode = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) ? S_IFDIR : 0;
717 st->st_dev = pb.hFileInfo.ioVRefNum;
718 st->st_ino = pb.hFileInfo.ioDirID;
719 st->st_size = pb.hFileInfo.ioFlLgLen;
720 st->st_mtime = pb.hFileInfo.ioFlMdDat;
721 st->st_ctime = pb.hFileInfo.ioFlCrDat;
722 st->st_btime = pb.hFileInfo.ioFlBkDat;
723 return 0;
724 }
725 }
726 st->st_mode = 0;
727 st->st_dev = 0;
728 st->st_ino = 0;
729 st->st_size = 0;
730 st->st_mtime = st->st_ctime = st->st_btime = 0;
731 errno = EIO;
732 return -1;
733 }
734 #endif /* __MACOS__ */
735 #endif /* HAVE_SYS_STAT_H */
736
737 #ifndef HAVE_STRLCPY
738 /*
739 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
740 *
741 * Permission to use, copy, modify, and distribute this software for any
742 * purpose with or without fee is hereby granted, provided that the above
743 * copyright notice and this permission notice appear in all copies.
744 *
745 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
746 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
747 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
748 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
749 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
750 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
751 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
752 */
753
754 #ifdef HAVE_SYS_TYPES_H
755 #include <sys/types.h>
756 #endif /* HAVE_SYS_TYPES_H */
757 #include <string.h>
758
759 /*
760 * Copy src to string dst of size siz. At most siz-1 characters
761 * will be copied. Always NUL terminates (unless siz == 0).
762 * Returns strlen(src); if retval >= siz, truncation occurred.
763 */
764 size_t
strlcpy(char * dst,const char * src,size_t siz)765 strlcpy(char *dst, const char *src, size_t siz)
766 {
767 register char *d = dst;
768 register const char *s = src;
769 register size_t n = siz;
770
771 /* Copy as many bytes as will fit */
772 if (n != 0 && --n != 0) {
773 do {
774 if ((*d++ = *s++) == 0)
775 break;
776 } while (--n != 0);
777 }
778
779 /* Not enough room in dst, add NUL and traverse rest of src */
780 if (n == 0) {
781 if (siz != 0)
782 *d = '\0'; /* NUL-terminate dst */
783 while (*s++)
784 ;
785 }
786
787 return(s - src - 1); /* count does not include NUL */
788 }
789 #endif /* strlcpy() */
790
791 #ifndef HAVE_STRLCAT
792 /*
793 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
794 *
795 * Permission to use, copy, modify, and distribute this software for any
796 * purpose with or without fee is hereby granted, provided that the above
797 * copyright notice and this permission notice appear in all copies.
798 *
799 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
800 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
801 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
802 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
803 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
804 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
805 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
806 */
807
808 #ifdef HAVE_SYS_TYPES_H
809 #include <sys/types.h>
810 #endif /* HAVE_SYS_TYPES_H */
811 #include <string.h>
812
813 /*
814 * Appends src to string dst of size siz (unlike strncat, siz is the
815 * full size of dst, not space left). At most siz-1 characters
816 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
817 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
818 * If retval >= siz, truncation occurred.
819 */
820 size_t
strlcat(char * dst,const char * src,size_t siz)821 strlcat(char *dst, const char *src, size_t siz)
822 {
823 register char *d = dst;
824 register const char *s = src;
825 register size_t n = siz;
826 size_t dlen;
827
828 /* Find the end of dst and adjust bytes left but don't go past end */
829 while (n-- != 0 && *d != '\0')
830 d++;
831 dlen = d - dst;
832 n = siz - dlen;
833
834 if (n == 0)
835 return(dlen + strlen(s));
836 while (*s != '\0') {
837 if (n != 1) {
838 *d++ = *s;
839 n--;
840 }
841 s++;
842 }
843 *d = '\0';
844
845 return(dlen + (s - src)); /* count does not include NUL */
846 }
847 #endif /* strlcat() */
848
849 #ifdef __DMC__
strcasecmp(const char * s1,const char * s2)850 int strcasecmp(const char *s1, const char *s2)
851 {
852 int c1,c2,i;
853
854 for( i=0; ; i++){
855 if( !s1[i] && !s2[i] ) return 0; //equal
856 if( !s1[i] || !s2[i] ) return 1;
857 c1= ( isupper(s1[i]) ? tolower(s1[i]) : s1[i] );
858 c2= ( isupper(s2[i]) ? tolower(s2[i]) : s2[i] );
859 if( c1 != c2 ) return 1;
860 }
861 return 0; //equal
862 }
863 #endif
864