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