source: trunk/libs/newlib/src/libgloss/arm/syscalls.c @ 546

Last change on this file since 546 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 19.5 KB
Line 
1/* Support files for GNU libc.  Files in the system namespace go here.
2   Files in the C namespace (ie those that do not start with an
3   underscore) go in .c.  */
4
5#include <_ansi.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <sys/fcntl.h>
9#include <stdio.h>
10#include <string.h>
11#include <time.h>
12#include <sys/time.h>
13#include <sys/times.h>
14#include <errno.h>
15#include <reent.h>
16#include <unistd.h>
17#include <sys/wait.h>
18#include "swi.h"
19
20/* Forward prototypes.  */
21int     _system     (const char *);
22int     _rename     (const char *, const char *);
23int     _isatty         (int);
24clock_t _times          (struct tms *);
25int     _gettimeofday   (struct timeval *, void *);
26int     _unlink         (const char *);
27int     _link           (void);
28int     _stat           (const char *, struct stat *);
29int     _fstat          (int, struct stat *);
30int     _swistat        (int fd, struct stat * st);
31caddr_t _sbrk           (int);
32int     _getpid         (int);
33int     _close          (int);
34clock_t _clock          (void);
35int     _swiclose       (int);
36int     _open           (const char *, int, ...);
37int     _swiopen        (const char *, int);
38int     _write          (int, char *, int);
39int     _swiwrite       (int, char *, int);
40int     _lseek          (int, int, int);
41int     _swilseek       (int, int, int);
42int     _read           (int, char *, int);
43int     _swiread        (int, char *, int);
44void    initialise_monitor_handles (void);
45
46static int      checkerror      (int);
47static int      error           (int);
48static int      get_errno       (void);
49
50/* Semihosting utilities.  */
51static void initialise_semihosting_exts (void);
52
53/* Struct used to keep track of the file position, just so we
54   can implement fseek(fh,x,SEEK_CUR).  */
55struct fdent
56{
57  int handle;
58  int pos;
59};
60
61#define MAX_OPEN_FILES 20
62
63/* User file descriptors (fd) are integer indexes into
64   the openfiles[] array. Error checking is done by using
65   findslot().
66
67   This openfiles array is manipulated directly by only
68   these 5 functions:
69
70        findslot() - Translate entry.
71        newslot() - Find empty entry.
72        initilise_monitor_handles() - Initialize entries.
73        _swiopen() - Initialize entry.
74        _close() - Handle stdout == stderr case.
75
76   Every other function must use findslot().  */
77
78static struct fdent openfiles [MAX_OPEN_FILES];
79
80static struct fdent*    findslot        (int);
81static int              newslot         (void);
82
83/* Register name faking - works in collusion with the linker.  */
84register char * stack_ptr asm ("sp");
85
86
87/* following is copied from libc/stdio/local.h to check std streams */
88extern void   __sinit (struct _reent *);
89#define CHECK_INIT(ptr) \
90  do                                            \
91    {                                           \
92      if ((ptr) && !(ptr)->__sdidinit)          \
93        __sinit (ptr);                          \
94    }                                           \
95  while (0)
96
97static int monitor_stdin;
98static int monitor_stdout;
99static int monitor_stderr;
100
101static int supports_ext_exit_extended = -1;
102static int supports_ext_stdout_stderr = -1;
103
104/* Return a pointer to the structure associated with
105   the user file descriptor fd. */ 
106static struct fdent*
107findslot (int fd)
108{
109  CHECK_INIT(_REENT);
110
111  /* User file descriptor is out of range. */
112  if ((unsigned int)fd >= MAX_OPEN_FILES)
113    return NULL;
114
115  /* User file descriptor is open? */
116  if (openfiles[fd].handle == -1)
117    return NULL;
118
119  /* Valid. */
120  return &openfiles[fd];
121}
122
123/* Return the next lowest numbered free file
124   structure, or -1 if we can't find one. */ 
125static int
126newslot (void)
127{
128  int i;
129
130  for (i = 0; i < MAX_OPEN_FILES; i++)
131    if (openfiles[i].handle == -1)
132      break;
133
134  if (i == MAX_OPEN_FILES)
135    return -1;
136
137  return i;
138}
139
140void
141initialise_monitor_handles (void)
142{
143  int i;
144 
145  /* Open the standard file descriptors by opening the special
146   * teletype device, ":tt", read-only to obtain a descritpor for
147   * standard input and write-only to obtain a descriptor for standard
148   * output. Finally, open ":tt" in append mode to obtain a descriptor
149   * for standard error. Since this is a write mode, most kernels will
150   * probably return the same value as for standard output, but the
151   * kernel can differentiate the two using the mode flag and return a
152   * different descriptor for standard error.
153   */
154
155#ifdef ARM_RDI_MONITOR
156  int volatile block[3];
157 
158  block[0] = (int) ":tt";
159  block[2] = 3;     /* length of filename */
160  block[1] = 0;     /* mode "r" */
161  monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
162
163  for (i = 0; i < MAX_OPEN_FILES; i ++)
164    openfiles[i].handle = -1;
165
166  if (_has_ext_stdout_stderr ())
167  {
168    block[0] = (int) ":tt";
169    block[2] = 3;     /* length of filename */
170    block[1] = 4;     /* mode "w" */
171    monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
172
173    block[0] = (int) ":tt";
174    block[2] = 3;     /* length of filename */
175    block[1] = 8;     /* mode "a" */
176    monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
177  }
178#else
179  int fh;
180  const char * name;
181
182  name = ":tt";
183  asm ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0"
184       : "=r"(fh)
185       : "i" (SWI_Open),"r"(name)
186       : "r0","r1");
187  monitor_stdin = fh;
188
189  if (_has_ext_stdout_stderr ())
190  {
191    name = ":tt";
192    asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
193         : "=r"(fh)
194         : "i" (SWI_Open),"r"(name)
195         : "r0","r1");
196    monitor_stdout = fh;
197
198    name = ":tt";
199    asm ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0"
200         : "=r"(fh)
201         : "i" (SWI_Open),"r"(name)
202         : "r0","r1");
203    monitor_stderr = fh;
204  }
205#endif
206
207  /* If we failed to open stderr, redirect to stdout. */
208  if (monitor_stderr == -1)
209    monitor_stderr = monitor_stdout;
210
211  openfiles[0].handle = monitor_stdin;
212  openfiles[0].pos = 0;
213
214  if (_has_ext_stdout_stderr ())
215  {
216    openfiles[1].handle = monitor_stdout;
217    openfiles[1].pos = 0;
218    openfiles[2].handle = monitor_stderr;
219    openfiles[2].pos = 0;
220  }
221}
222
223int
224_has_ext_exit_extended (void)
225{
226  if (supports_ext_exit_extended < 0)
227  {
228    initialise_semihosting_exts ();
229  }
230
231  return supports_ext_exit_extended;
232}
233
234int
235_has_ext_stdout_stderr (void)
236{
237  if (supports_ext_stdout_stderr < 0)
238  {
239    initialise_semihosting_exts ();
240  }
241
242  return supports_ext_stdout_stderr;
243}
244
245static void
246initialise_semihosting_exts (void)
247{
248  supports_ext_exit_extended = 0;
249  supports_ext_stdout_stderr = 1;
250
251#if SEMIHOST_V2
252  char features[1];
253  if (_get_semihosting_exts (features, 0, 1) > 0)
254  {
255     supports_ext_exit_extended
256       = features[0] & (1 << SH_EXT_EXIT_EXTENDED_BITNUM);
257     supports_ext_stdout_stderr
258       = features[0] & (1 << SH_EXT_STDOUT_STDERR_BITNUM);
259  }
260#endif
261}
262
263int
264_get_semihosting_exts (char* features, int offset, int num)
265{
266  int len;
267  struct fdent *pfd;
268  int fd = _open (":semihosting-features", O_RDONLY);
269  memset (features, 0, num);
270
271  if (fd == -1)
272  {
273    return -1;
274  }
275
276  pfd = findslot (fd);
277
278#ifdef ARM_RDI_MONITOR
279  len = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
280#else
281  asm ("mov r0,%2; swi %a1; mov %0, r0"
282       : "=r"(len)
283       : "i" (SWI_Flen),"r"(pfd->handle)
284       : "r0");
285#endif
286
287  if (len < NUM_SHFB_MAGIC
288      || num > (len - NUM_SHFB_MAGIC))
289  {
290     _close (fd);
291     return -1;
292  }
293
294  char buffer[NUM_SHFB_MAGIC];
295  int n_read = _read (fd, buffer, NUM_SHFB_MAGIC);
296
297  if (n_read < NUM_SHFB_MAGIC
298      || buffer[0] != SHFB_MAGIC_0
299      || buffer[1] != SHFB_MAGIC_1
300      || buffer[2] != SHFB_MAGIC_2
301      || buffer[3] != SHFB_MAGIC_3)
302  {
303     _close (fd);
304     return -1;
305  }
306
307  if (_lseek (fd, offset, SEEK_CUR) < 0)
308  {
309     _close (fd);
310     return -1;
311  }
312
313  n_read = _read (fd, features, num);
314
315  _close (fd);
316
317  return checkerror (n_read);
318}
319
320static int
321get_errno (void)
322{
323#ifdef ARM_RDI_MONITOR
324  return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
325#else
326  register r0 asm("r0");
327  asm ("swi %a1" : "=r"(r0) : "i" (SWI_GetErrno));
328  return r0;
329#endif
330}
331
332/* Set errno and return result. */
333static int
334error (int result)
335{
336  errno = get_errno ();
337  return result;
338}
339
340/* Check the return and set errno appropriately. */
341static int
342checkerror (int result)
343{
344  if (result == -1)
345    return error (-1);
346  return result;
347}
348
349/* fh, is a valid internal file handle.
350   ptr, is a null terminated string.
351   len, is the length in bytes to read.
352   Returns the number of bytes *not* written. */
353int
354_swiread (int fh,
355          char * ptr,
356          int len)
357{
358#ifdef ARM_RDI_MONITOR
359  int block[3];
360 
361  block[0] = fh;
362  block[1] = (int) ptr;
363  block[2] = len;
364 
365  return checkerror (do_AngelSWI (AngelSWI_Reason_Read, block));
366#else
367  register r0 asm("r0");
368  register r1 asm("r1");
369  register r2 asm("r2");
370  r0 = fh;
371  r1 = (int)ptr;
372  r2 = len;
373  asm ("swi %a4"
374       : "=r" (r0)
375       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Read));
376  return checkerror (r0);
377#endif
378}
379
380/* fd, is a valid user file handle.
381   Translates the return of _swiread into
382   bytes read. */
383int __attribute__((weak))
384_read (int fd,
385       char * ptr,
386       int len)
387{
388  int res;
389  struct fdent *pfd;
390
391  pfd = findslot (fd);
392  if (pfd == NULL)
393    {
394      errno = EBADF;
395      return -1;
396    }
397
398  res = _swiread (pfd->handle, ptr, len);
399
400  if (res == -1)
401    return res;
402
403  pfd->pos += len - res;
404
405  /* res == len is not an error,
406     at least if we want feof() to work.  */
407  return len - res;
408}
409
410/* fd, is a user file descriptor. */
411int
412_swilseek (int fd,
413        int ptr,
414        int dir)
415{
416  int res;
417  struct fdent *pfd;
418
419  /* Valid file descriptor? */
420  pfd = findslot (fd);
421  if (pfd == NULL)
422    {
423      errno = EBADF;
424      return -1;
425    }
426
427  /* Valid whence? */
428  if ((dir != SEEK_CUR)
429      && (dir != SEEK_SET)
430      && (dir != SEEK_END))
431    {
432      errno = EINVAL;
433      return -1;
434    }
435
436  /* Convert SEEK_CUR to SEEK_SET */
437  if (dir == SEEK_CUR)
438    {
439      ptr = pfd->pos + ptr;
440      /* The resulting file offset would be negative. */
441      if (ptr < 0)
442        {
443          errno = EINVAL;
444          if ((pfd->pos > 0) && (ptr > 0))
445            errno = EOVERFLOW;
446          return -1;
447        }
448      dir = SEEK_SET;
449    }
450 
451#ifdef ARM_RDI_MONITOR
452  int block[2];
453  if (dir == SEEK_END)
454    {
455      block[0] = pfd->handle;
456      res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, block));
457      if (res == -1)
458        return -1;
459      ptr += res;
460    }
461 
462  /* This code only does absolute seeks.  */
463  block[0] = pfd->handle;
464  block[1] = ptr;
465  res = checkerror (do_AngelSWI (AngelSWI_Reason_Seek, block));
466#else
467  if (dir == SEEK_END)
468    {
469      asm ("mov r0, %2; swi %a1; mov %0, r0"
470           : "=r" (res)
471           : "i" (SWI_Flen), "r" (pfd->handle)
472           : "r0");
473      checkerror (res);
474      if (res == -1)
475        return -1;
476      ptr += res;
477    }
478
479  /* This code only does absolute seeks.  */
480  asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0"
481       : "=r" (res)
482       : "i" (SWI_Seek), "r" (pfd->handle), "r" (ptr)
483       : "r0", "r1");
484  checkerror (res);
485#endif
486  /* At this point ptr is the current file position. */
487  if (res >= 0)
488    {
489      pfd->pos = ptr;
490      return ptr;
491    }
492  else
493    return -1;
494}
495
496_lseek (int fd,
497        int ptr,
498        int dir)
499{
500  return _swilseek (fd, ptr, dir);
501}
502
503/* fh, is a valid internal file handle.
504   Returns the number of bytes *not* written. */
505int
506_swiwrite (
507           int    fh,
508           char * ptr,
509           int    len)
510{
511#ifdef ARM_RDI_MONITOR
512  int block[3];
513 
514  block[0] = fh;
515  block[1] = (int) ptr;
516  block[2] = len;
517 
518  return checkerror (do_AngelSWI (AngelSWI_Reason_Write, block));
519#else
520  register r0 asm("r0");
521  register r1 asm("r1");
522  register r2 asm("r2");
523  r0 = fh;
524  r1 = (int)ptr;
525  r2 = len;
526  asm ("swi %a4"
527       : "=r" (r0)
528       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Write));
529  return checkerror (r0);
530#endif
531}
532
533/* fd, is a user file descriptor. */
534int __attribute__((weak))
535_write (int    fd,
536        char * ptr,
537        int    len)
538{
539  int res;
540  struct fdent *pfd;
541
542  pfd = findslot (fd);
543  if (pfd == NULL)
544    {
545      errno = EBADF;
546      return -1;
547    }
548
549  res = _swiwrite (pfd->handle, ptr,len);
550
551  /* Clearly an error. */
552  if (res < 0)
553    return -1;
554
555  pfd->pos += len - res;
556
557  /* We wrote 0 bytes?
558     Retrieve errno just in case. */
559  if ((len - res) == 0)
560    return error (0);
561 
562  return (len - res);
563}
564
565int
566_swiopen (const char * path, int flags)
567{
568  int aflags = 0, fh;
569#ifdef ARM_RDI_MONITOR
570  int block[3];
571#endif
572 
573  int fd = newslot ();
574
575  if (fd == -1)
576    {
577      errno = EMFILE;
578      return -1;
579    }
580 
581  /* It is an error to open a file that already exists. */
582  if ((flags & O_CREAT) 
583      && (flags & O_EXCL))
584    {
585      struct stat st;
586      int res;
587      res = _stat (path, &st);
588      if (res != -1)
589        {
590          errno = EEXIST;
591          return -1;
592        }
593    }
594
595  /* The flags are Unix-style, so we need to convert them. */ 
596#ifdef O_BINARY
597  if (flags & O_BINARY)
598    aflags |= 1;
599#endif
600 
601  /* In O_RDONLY we expect aflags == 0. */
602
603  if (flags & O_RDWR) 
604    aflags |= 2;
605
606  if ((flags & O_CREAT)
607      || (flags & O_TRUNC)
608      || (flags & O_WRONLY))
609    aflags |= 4;
610
611  if (flags & O_APPEND)
612    {
613      /* Can't ask for w AND a; means just 'a'.  */
614      aflags &= ~4;
615      aflags |= 8;
616    }
617 
618#ifdef ARM_RDI_MONITOR
619  block[0] = (int) path;
620  block[2] = strlen (path);
621  block[1] = aflags;
622 
623  fh = do_AngelSWI (AngelSWI_Reason_Open, block);
624 
625#else
626  asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0"
627       : "=r"(fh)
628       : "i" (SWI_Open),"r"(path),"r"(aflags)
629       : "r0","r1");
630#endif
631 
632  /* Return a user file descriptor or an error. */
633  if (fh >= 0)
634    {
635      openfiles[fd].handle = fh;
636      openfiles[fd].pos = 0;
637      return fd;
638    }
639  else
640    return error (fh);
641}
642
643int
644_open (const char * path, int flags, ...)
645{
646  return _swiopen (path, flags);
647}
648
649/* fh, is a valid internal file handle. */
650int
651_swiclose (int fh)
652{
653#ifdef ARM_RDI_MONITOR
654  return checkerror (do_AngelSWI (AngelSWI_Reason_Close, &fh));
655#else
656  register r0 asm("r0");
657  r0 = fh;
658  asm ("swi %a2" 
659       : "=r"(r0) 
660       : "0"(r0), "i" (SWI_Close));
661  return checkerror (r0);
662#endif
663}
664
665/* fd, is a user file descriptor. */
666int
667_close (int fd)
668{
669  int res;
670  struct fdent *pfd;
671
672  pfd = findslot (fd);
673  if (pfd == NULL)
674    {
675      errno = EBADF;
676      return -1;
677    }
678
679  /* Handle stderr == stdout. */
680  if ((fd == 1 || fd == 2)
681      && (openfiles[1].handle == openfiles[2].handle))
682    {
683      pfd->handle = -1;
684      return 0;
685    }
686
687  /* Attempt to close the handle. */
688  res = _swiclose (pfd->handle);
689
690  /* Reclaim handle? */
691  if (res == 0)
692    pfd->handle = -1;
693
694  return res;
695}
696
697int __attribute__((weak))
698_getpid (int n __attribute__ ((unused)))
699{
700  return 1;
701}
702
703/* Heap limit returned from SYS_HEAPINFO Angel semihost call.  */
704uint __heap_limit = 0xcafedead;
705
706caddr_t __attribute__((weak))
707_sbrk (int incr)
708{
709  extern char end asm ("end"); /* Defined by the linker.  */
710  static char * heap_end;
711  char * prev_heap_end;
712
713  if (heap_end == NULL)
714    heap_end = & end;
715 
716  prev_heap_end = heap_end;
717 
718  if ((heap_end + incr > stack_ptr)
719      /* Honour heap limit if it's valid.  */
720      || (__heap_limit != 0xcafedead && heap_end + incr > __heap_limit))
721    {
722      /* Some of the libstdc++-v3 tests rely upon detecting
723         out of memory errors, so do not abort here.  */
724#if 0
725      extern void abort (void);
726
727      _write (1, "_sbrk: Heap and stack collision\n", 32);
728     
729      abort ();
730#else
731      errno = ENOMEM;
732      return (caddr_t) -1;
733#endif
734    }
735 
736  heap_end += incr;
737
738  return (caddr_t) prev_heap_end;
739}
740
741int 
742_swistat (int fd, struct stat * st)
743{
744  struct fdent *pfd;
745  int res;
746
747  pfd = findslot (fd);
748  if (pfd == NULL)
749    {
750      errno = EBADF;
751      return -1;
752    }
753
754  /* Always assume a character device,
755     with 1024 byte blocks. */
756  st->st_mode |= S_IFCHR;
757  st->st_blksize = 1024;
758#ifdef ARM_RDI_MONITOR
759  res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
760#else
761  asm ("mov r0, %2; swi %a1; mov %0, r0"
762       : "=r" (res)
763       : "i" (SWI_Flen), "r" (pfd->handle)
764       : "r0");
765  checkerror (res);
766#endif
767  if (res == -1)
768    return -1;
769  /* Return the file size. */
770  st->st_size = res;
771  return 0;
772}
773
774int __attribute__((weak))
775_fstat (int fd, struct stat * st)
776{
777  memset (st, 0, sizeof (* st));
778  return _swistat (fd, st);
779}
780
781int __attribute__((weak))
782_stat (const char *fname, struct stat *st)
783{
784  int fd, res;
785  memset (st, 0, sizeof (* st));
786  /* The best we can do is try to open the file readonly. 
787     If it exists, then we can guess a few things about it. */
788  if ((fd = _open (fname, O_RDONLY)) == -1)
789    return -1;
790  st->st_mode |= S_IFREG | S_IREAD;
791  res = _swistat (fd, st);
792  /* Not interested in the error. */
793  _close (fd); 
794  return res;
795}
796
797int __attribute__((weak))
798_link (void)
799{
800  errno = ENOSYS;
801  return -1;
802}
803
804int
805_unlink (const char *path)
806{
807  int res;
808#ifdef ARM_RDI_MONITOR
809  int block[2];
810  block[0] = (int)path;
811  block[1] = strlen(path);
812  res = do_AngelSWI (AngelSWI_Reason_Remove, block);
813#else
814  register r0 asm("r0");
815  r0 = (int)path;
816  asm ("swi %a2" 
817       : "=r"(r0)
818       : "0"(r0), "i" (SWI_Remove));
819  res = r0;
820#endif
821  if (res == -1) 
822    return error (res);
823  return 0;
824}
825
826int
827_gettimeofday (struct timeval * tp, void * tzvp)
828{
829  struct timezone *tzp = tzvp;
830  if (tp)
831    {
832    /* Ask the host for the seconds since the Unix epoch.  */
833#ifdef ARM_RDI_MONITOR
834      tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL);
835#else
836      {
837        int value;
838        asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0");
839        tp->tv_sec = value;
840      }
841#endif
842      tp->tv_usec = 0;
843    }
844
845  /* Return fixed data for the timezone.  */
846  if (tzp)
847    {
848      tzp->tz_minuteswest = 0;
849      tzp->tz_dsttime = 0;
850    }
851
852  return 0;
853}
854
855/* Return a clock that ticks at 100Hz.  */
856clock_t 
857_clock (void)
858{
859  clock_t timeval;
860
861#ifdef ARM_RDI_MONITOR
862  timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL);
863#else
864  asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0");
865#endif
866  return timeval;
867}
868
869/* Return a clock that ticks at 100Hz.  */
870clock_t
871_times (struct tms * tp)
872{
873  clock_t timeval = _clock();
874
875  if (tp)
876    {
877      tp->tms_utime  = timeval; /* user time */
878      tp->tms_stime  = 0;       /* system time */
879      tp->tms_cutime = 0;       /* user time, children */
880      tp->tms_cstime = 0;       /* system time, children */
881    }
882 
883  return timeval;
884};
885
886
887int
888_isatty (int fd)
889{
890  struct fdent *pfd;
891  int tty;
892
893  pfd = findslot (fd);
894  if (pfd == NULL)
895    {
896      errno = EBADF;
897      return 0;
898    }
899
900#ifdef ARM_RDI_MONITOR
901  tty = do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle);
902#else
903  register r0 asm("r0");
904  r0 = pfd->handle;
905  asm ("swi %a2"
906       : "=r" (r0)
907       : "0"(r0), "i" (SWI_IsTTY));
908  tty = r0;
909#endif
910
911  if (tty == 1)
912    return 1;
913  errno = get_errno ();
914  return 0;
915}
916
917int
918_system (const char *s)
919{
920#ifdef ARM_RDI_MONITOR
921  int block[2];
922  int e;
923
924  /* Hmmm.  The ARM debug interface specification doesn't say whether
925     SYS_SYSTEM does the right thing with a null argument, or assign any
926     meaning to its return value.  Try to do something reasonable....  */
927  if (!s)
928    return 1;  /* maybe there is a shell available? we can hope. :-P */
929  block[0] = (int)s;
930  block[1] = strlen (s);
931  e = checkerror (do_AngelSWI (AngelSWI_Reason_System, block));
932  if ((e >= 0) && (e < 256))
933    {
934      /* We have to convert e, an exit status to the encoded status of
935         the command.  To avoid hard coding the exit status, we simply
936         loop until we find the right position.  */
937      int exit_code;
938
939      for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1)
940        continue;
941    }
942  return e;
943#else
944  register r0 asm("r0");
945  r0 = (int)s;
946  asm ("swi %a2" 
947       : "=r" (r0)
948       : "0"(r0), "i" (SWI_CLI));
949  return checkerror (r0);
950#endif
951}
952
953int
954_rename (const char * oldpath, const char * newpath)
955{
956#ifdef ARM_RDI_MONITOR
957  int block[4];
958  block[0] = (int)oldpath;
959  block[1] = strlen(oldpath);
960  block[2] = (int)newpath;
961  block[3] = strlen(newpath);
962  return checkerror (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;
963#else
964  register r0 asm("r0");
965  register r1 asm("r1");
966  r0 = (int)oldpath;
967  r1 = (int)newpath;
968  asm ("swi %a3" 
969       : "=r" (r0)
970       : "0" (r0), "r" (r1), "i" (SWI_Rename));
971  return checkerror (r0);
972#endif
973}
Note: See TracBrowser for help on using the repository browser.