~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/libiberty/mpw.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* MPW-Unix compatibility library.
 
2
   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
 
3
 
 
4
This file is part of the libiberty library.
 
5
Libiberty is free software; you can redistribute it and/or
 
6
modify it under the terms of the GNU Library General Public
 
7
License as published by the Free Software Foundation; either
 
8
version 2 of the License, or (at your option) any later version.
 
9
 
 
10
Libiberty is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
Library General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU Library General Public
 
16
License along with libiberty; see the file COPYING.LIB.  If
 
17
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
Boston, MA 02111-1307, USA.  */
 
19
 
 
20
/* This should only be compiled and linked under MPW. */
 
21
 
 
22
#include "mpw.h"
 
23
 
 
24
#include <stdlib.h>
 
25
 
 
26
#ifndef USE_MW_HEADERS
 
27
#include <sys/time.h>
 
28
#include <sys/resource.h>
 
29
#endif
 
30
 
 
31
#include <Types.h>
 
32
#include <Files.h>
 
33
 
 
34
#include <Timer.h>
 
35
 
 
36
/* Initialize to 0 at first, then set to errno_max() later.  */
 
37
 
 
38
int sys_nerr = 0;
 
39
 
 
40
/* Debug flag for pathname hacking.  Set this to one and rebuild. */
 
41
 
 
42
int DebugPI = -1;
 
43
 
 
44
void
 
45
mpwify_filename(char *unixname, char *macname)
 
46
{
 
47
  int i, j;
 
48
 
 
49
  /* (should truncate 255 chars from end of name, not beginning) */
 
50
  if (strlen (unixname) > 255)
 
51
    {
 
52
      fprintf (stderr, "Pathname \"%s\" is too long for Macs, truncating\n",
 
53
               unixname);
 
54
    }
 
55
  j = 0;
 
56
  /* If you're going to end up with one or more colons in the middle of a
 
57
     path after an all-Unix relative path is translated, you must add a
 
58
     colon on the front, so that the first component is not thought to be
 
59
     a disk name.  */
 
60
  if (unixname[0] != '/' && ! strchr (unixname, ':') && strchr (unixname, '/'))
 
61
    {
 
62
      macname[j++] = ':';
 
63
    }
 
64
  for (i = 0; unixname[i] != '\0' && i < 255; ++i)
 
65
    {
 
66
      if (i == 0 && unixname[i] == '/')
 
67
        {
 
68
          if (strncmp (unixname, "/tmp/", 5) == 0)
 
69
            {
 
70
              /* A temporary name, make a more Mac-flavored tmpname. */
 
71
              /* A better choice would be {Boot}Trash:foo, but
 
72
                 that would require being able to identify the
 
73
                 boot disk's and trashcan's name.  Another option
 
74
                 would be to have an env var, so user can point it
 
75
                 at a ramdisk. */
 
76
              macname[j++] = ':';
 
77
              macname[j++] = 't';
 
78
              macname[j++] = 'm';
 
79
              macname[j++] = 'p';
 
80
              macname[j++] = '_';
 
81
              i += 4;
 
82
            }
 
83
          else
 
84
            {
 
85
              /* Don't copy the leading slash. */
 
86
            }
 
87
        }
 
88
      else if (unixname[i] == ':' && unixname[i+1] == '/')
 
89
        {
 
90
          macname[j++] = ':';
 
91
          i += 1;
 
92
        }
 
93
      else if (unixname[i] == '.' && unixname[i+1] == '/')
 
94
        {
 
95
          macname[j++] = ':';
 
96
          i += 1;
 
97
        }
 
98
      else if (unixname[i] == '.' && unixname[i+1] == '.' && unixname[i+2] == '/')
 
99
        {
 
100
          macname[j++] = ':';
 
101
          macname[j++] = ':';
 
102
          i += 2;
 
103
        }
 
104
      else if (unixname[i] == '/')
 
105
        {
 
106
          macname[j++] = ':';
 
107
        }
 
108
      else
 
109
        {
 
110
          macname[j++] = unixname[i];
 
111
        }
 
112
    }
 
113
  macname[j] = '\0';
 
114
  /* Allow for getting the debug flag from an env var; quite useful. */
 
115
  if (DebugPI < 0)
 
116
    DebugPI = (*(getenv ("DEBUG_PATHNAMES")) == '1' ? 1 : 0);
 
117
  if (DebugPI)
 
118
    {
 
119
      fprintf (stderr, "# Made \"%s\"\n", unixname);
 
120
      fprintf (stderr, "# into \"%s\"\n", macname);
 
121
    }
 
122
}
 
123
 
 
124
/* MPW-flavored basename finder. */
 
125
 
 
126
char *
 
127
mpw_basename (name)
 
128
  char *name;
 
129
{
 
130
  char *base = name;
 
131
 
 
132
  while (*name)
 
133
    {
 
134
      if (*name++ == ':')
 
135
        {
 
136
          base = name;
 
137
        }
 
138
    }
 
139
  return base;
 
140
}
 
141
 
 
142
/* Mixed MPW/Unix basename finder.  This can be led astray by
 
143
   filenames with slashes in them and come up with a basename that
 
144
   either corresponds to no file or (worse) to some other file, so
 
145
   should only be tried if other methods of finding a file via a
 
146
   basename have failed.  */
 
147
 
 
148
char *
 
149
mpw_mixed_basename (name)
 
150
  char *name;
 
151
{
 
152
  char *base = name;
 
153
 
 
154
  while (*name)
 
155
    {
 
156
      if (*name == '/' || *name == ':')
 
157
        {
 
158
          base = name + 1;
 
159
        }
 
160
      ++name;
 
161
    }
 
162
  return base;
 
163
}
 
164
 
 
165
/* This function is fopen() modified to create files that are type TEXT
 
166
   or 'BIN ', and always of type 'MPS '.  */
 
167
 
 
168
FILE *
 
169
mpw_fopen (char *name, char *mode)
 
170
{
 
171
#undef fopen
 
172
  int errnum;
 
173
  FILE *fp;
 
174
  char tmpname[256];
 
175
 
 
176
  mpwify_filename (name, tmpname);
 
177
  PROGRESS (1);
 
178
  fp = fopen (tmpname, mode);
 
179
  errnum = errno;
 
180
 
 
181
  /* If writing, need to set type and creator usefully. */
 
182
  if (strchr (mode, 'w'))
 
183
    {
 
184
      char *pname = (char *) malloc (strlen (tmpname) + 2);
 
185
      OSErr e;
 
186
      struct FInfo fi;
 
187
 
 
188
      pname[0] = strlen (tmpname);
 
189
      strcpy (pname+1, tmpname);
 
190
        
 
191
      e = GetFInfo ((ConstStr255Param) pname, 0, &fi);
 
192
      /* should do spiffier error handling */
 
193
      if (e != 0)
 
194
        fprintf(stderr, "GetFInfo returns %d\n", e);
 
195
      if (strchr (mode, 'b'))
 
196
        {
 
197
          fi.fdType = (OSType) 'BIN ';
 
198
        }
 
199
      else
 
200
        {
 
201
          fi.fdType = (OSType) 'TEXT';
 
202
        }
 
203
      fi.fdCreator = (OSType) 'MPS ';
 
204
      e = SetFInfo ((ConstStr255Param) pname, 0, &fi);
 
205
      if (e != 0)
 
206
        fprintf(stderr, "SetFInfo returns %d\n", e);
 
207
      free (pname);
 
208
    }
 
209
  if (fp == NULL)
 
210
    errno = errnum;
 
211
  return fp;
 
212
}
 
213
 
 
214
/* This is a version of fseek() modified to fill the file with zeros
 
215
   if seeking past the end of it.  */
 
216
 
 
217
#define ZEROBLKSIZE 4096
 
218
 
 
219
char zeros[ZEROBLKSIZE];
 
220
 
 
221
int
 
222
mpw_fseek (FILE *fp, int offset, int whence)
 
223
{
 
224
#undef fseek
 
225
  int cursize, numleft;
 
226
 
 
227
  PROGRESS (1);
 
228
  if (whence == SEEK_SET)
 
229
    {
 
230
      fseek (fp, 0, SEEK_END);
 
231
      cursize = ftell (fp);
 
232
      if (offset > cursize)
 
233
        {
 
234
          numleft = offset - cursize;
 
235
          while (numleft > ZEROBLKSIZE)
 
236
            {
 
237
              /* This might fail, should check for that. */
 
238
              PROGRESS (1);
 
239
              fwrite (zeros, 1, ZEROBLKSIZE, fp);
 
240
              numleft -= ZEROBLKSIZE;
 
241
            }
 
242
          PROGRESS (1);
 
243
          fwrite (zeros, 1, numleft, fp);
 
244
          fflush (fp);
 
245
        }
 
246
    }
 
247
  return fseek (fp, offset, whence);
 
248
}
 
249
 
 
250
int
 
251
mpw_fread (char *ptr, int size, int nitems, FILE *stream)
 
252
{
 
253
#undef fread
 
254
  int rslt;
 
255
 
 
256
  PROGRESS (1);
 
257
  rslt = fread (ptr, size, nitems, stream);
 
258
  PROGRESS (1);
 
259
  return rslt;
 
260
}
 
261
 
 
262
int
 
263
mpw_fwrite (char *ptr, int size, int nitems, FILE *stream)
 
264
{
 
265
#undef fwrite
 
266
  int rslt;
 
267
 
 
268
  PROGRESS (1);
 
269
  rslt = fwrite (ptr, size, nitems, stream);
 
270
  PROGRESS (1);
 
271
  return rslt;
 
272
}
 
273
 
 
274
int
 
275
link ()
 
276
{
 
277
  fprintf (stderr, "link not available!\n");
 
278
  mpw_abort ();
 
279
}
 
280
 
 
281
int
 
282
fork ()
 
283
{
 
284
  fprintf (stderr, "fork not available!\n");
 
285
  mpw_abort ();
 
286
}
 
287
 
 
288
int
 
289
vfork ()
 
290
{
 
291
  fprintf (stderr, "vfork not available!\n");
 
292
  mpw_abort ();
 
293
  return (-1);
 
294
}
 
295
 
 
296
int
 
297
pipe (int *fd)
 
298
{
 
299
  fprintf (stderr, "pipe not available!\n");
 
300
  mpw_abort ();
 
301
  return (-1);
 
302
}
 
303
 
 
304
#ifndef USE_MW_HEADERS
 
305
int
 
306
execvp (char *file, char **argv)
 
307
{
 
308
  fprintf (stderr, "execvp not available!\n");
 
309
  mpw_abort ();
 
310
  return (-1);
 
311
}
 
312
 
 
313
int
 
314
execv (char *path, char **argv)
 
315
{
 
316
  fprintf (stderr, "execv not available!\n");
 
317
  mpw_abort ();
 
318
  return (-1);
 
319
}
 
320
#endif
 
321
 
 
322
int
 
323
kill (int pid, int sig)
 
324
{
 
325
  fprintf (stderr, "kill not available!\n");
 
326
  mpw_abort ();
 
327
  return (-1);
 
328
}
 
329
 
 
330
int
 
331
wait (int *status)
 
332
{
 
333
  *status = 0;
 
334
  return 0;
 
335
}
 
336
 
 
337
#ifndef USE_MW_HEADERS
 
338
int
 
339
sleep (int seconds)
 
340
{
 
341
  unsigned long start_time, now;
 
342
 
 
343
  time (&start_time);
 
344
 
 
345
  while (1)
 
346
    {
 
347
      PROGRESS (1);
 
348
      time (&now);
 
349
      if (now > start_time + seconds)
 
350
        return 0;
 
351
    }
 
352
}
 
353
#endif
 
354
 
 
355
void
 
356
putenv (char *str)
 
357
{
 
358
  /* The GCC driver calls this to do things for collect2, but we
 
359
     don't care about collect2. */
 
360
}
 
361
 
 
362
int
 
363
chmod (char *path, int mode)
 
364
{
 
365
  /* Pretend it was all OK. */
 
366
  return 0;
 
367
}
 
368
 
 
369
#ifndef USE_MW_HEADERS
 
370
int
 
371
getuid ()
 
372
{
 
373
  /* One value is as good as another... */
 
374
  return 0;
 
375
}
 
376
 
 
377
int
 
378
getgid ()
 
379
{
 
380
  /* One value is as good as another... */
 
381
  return 0;
 
382
}
 
383
#endif
 
384
 
 
385
/* Instead of coredumping, which is not a normal Mac facility, we
 
386
   drop into Macsbug.  If we then "g" from Macsbug, the program will
 
387
   exit cleanly. */
 
388
 
 
389
void
 
390
mpw_abort ()
 
391
{
 
392
  /* Make sure no output still buffered up, then zap into MacsBug. */
 
393
  fflush(stdout);
 
394
  fflush(stderr);
 
395
  printf("## Abort! ##\n");
 
396
#ifdef MPW_SADE
 
397
  SysError(8005);
 
398
#else 
 
399
  Debugger();
 
400
#endif
 
401
  /* "g" in MacsBug will then cause a regular error exit. */
 
402
  exit (1);
 
403
}
 
404
 
 
405
/* Imitation getrusage based on the ANSI clock() function. */
 
406
 
 
407
int
 
408
getrusage (int who, struct rusage *rusage)
 
409
{
 
410
  int clk = clock ();
 
411
 
 
412
#if 0
 
413
  rusage->ru_utime.tv_sec = clk / CLOCKS_PER_SEC;
 
414
  rusage->ru_utime.tv_usec = ((clk * 1000) / CLOCKS_PER_SEC) * 1000;
 
415
  rusage->ru_stime.tv_sec = 0;
 
416
  rusage->ru_stime.tv_usec = 0;
 
417
#endif
 
418
}
 
419
 
 
420
int
 
421
sbrk ()
 
422
{
 
423
  return 0;
 
424
}
 
425
 
 
426
#ifndef USE_MW_HEADERS
 
427
int
 
428
isatty (int fd)
 
429
{
 
430
  return 0;
 
431
}
 
432
 
 
433
/* This is inherited from Timothy Murray's Posix library. */
 
434
 
 
435
#include "utime.h"
 
436
 
 
437
int
 
438
utime (char *filename, struct utimbuf *times)
 
439
{
 
440
  CInfoPBRec cipbr;
 
441
  HFileInfo *fpb = (HFileInfo *) &cipbr;
 
442
  DirInfo *dpb = (DirInfo *) &cipbr;
 
443
  unsigned char pname[256];
 
444
  short err;
 
445
  
 
446
  strcpy ((char *) pname, filename);
 
447
  c2pstr (pname);
 
448
 
 
449
  dpb->ioDrDirID = 0L;
 
450
  fpb->ioNamePtr = pname;
 
451
  fpb->ioVRefNum = 0;
 
452
  fpb->ioFDirIndex = 0;
 
453
  fpb->ioFVersNum = 0;
 
454
  err = PBGetCatInfo (&cipbr, 0);
 
455
  if (err != noErr) {
 
456
    errno = ENOENT;
 
457
    return -1;
 
458
  }
 
459
  dpb->ioDrDirID = 0L;
 
460
  fpb->ioFlMdDat = times->modtime;
 
461
  fpb->ioFlCrDat = times->actime;
 
462
  err = PBSetCatInfo (&cipbr, 0);
 
463
  if (err != noErr) {
 
464
    errno = EACCES;
 
465
    return -1;
 
466
  }
 
467
  return 0;
 
468
}
 
469
 
 
470
int
 
471
mkdir (char *path, int mode)
 
472
{
 
473
  errno = ENOSYS;
 
474
  return -1;
 
475
}
 
476
 
 
477
int
 
478
rmdir ()
 
479
{
 
480
  errno = ENOSYS;
 
481
  return -1;
 
482
}
 
483
#endif
 
484
 
 
485
chown ()
 
486
{
 
487
  errno = ENOSYS;
 
488
  return -1;
 
489
}
 
490
 
 
491
char *myenviron[] = {NULL};
 
492
 
 
493
char **environ = myenviron;
 
494
 
 
495
#ifndef USE_MW_HEADERS
 
496
 
 
497
/* Minimal 'stat' emulation: tells directories from files and
 
498
   gives length and mtime.
 
499
 
 
500
   Derived from code written by Guido van Rossum, CWI, Amsterdam
 
501
   and placed by him in the public domain.  */
 
502
 
 
503
extern int __uid, __gid;
 
504
 
 
505
int __uid = 0;
 
506
int __gid = 0;
 
507
 
 
508
/* Bits in ioFlAttrib: */
 
509
#define LOCKBIT (1<<0)          /* File locked */
 
510
#define DIRBIT  (1<<4)          /* It's a directory */
 
511
 
 
512
/* Macified "stat" in which filename is given relative to a directory,
 
513
   specified by long DirID.  */
 
514
 
 
515
static int
 
516
_stat (char *name, long dirid, struct stat *buf)
 
517
{
 
518
  CInfoPBRec cipbr;
 
519
  HFileInfo *fpb = (HFileInfo*) &cipbr;
 
520
  DirInfo *dpb = (DirInfo*) &cipbr;
 
521
  Str255 pname;
 
522
  short err;
 
523
 
 
524
  /* Make a temp copy of the name and pascalize. */
 
525
  strcpy ((char *) pname, name);
 
526
  c2pstr (pname);
 
527
  
 
528
  cipbr.dirInfo.ioDrDirID = dirid;
 
529
  cipbr.hFileInfo.ioNamePtr = pname;
 
530
  cipbr.hFileInfo.ioVRefNum = 0;
 
531
  cipbr.hFileInfo.ioFDirIndex = 0;
 
532
  cipbr.hFileInfo.ioFVersNum = 0;
 
533
  err = PBGetCatInfo (&cipbr, 0);
 
534
  if (err != noErr)
 
535
    {
 
536
      errno = ENOENT;
 
537
      return -1;
 
538
    }
 
539
  /* Mac files are readable if they can be accessed at all. */
 
540
  buf->st_mode = 0444;
 
541
  /* Mark unlocked files as writeable. */
 
542
  if (!(fpb->ioFlAttrib & LOCKBIT))
 
543
    buf->st_mode |= 0222;
 
544
  if (fpb->ioFlAttrib & DIRBIT)
 
545
    {
 
546
      /* Mark directories as "executable". */
 
547
      buf->st_mode |= 0111 | S_IFDIR;
 
548
      buf->st_size = dpb->ioDrNmFls;
 
549
      buf->st_rsize = 0;
 
550
    }
 
551
  else
 
552
    {
 
553
      buf->st_mode |= S_IFREG;
 
554
      /* Mark apps as "executable". */
 
555
      if (fpb->ioFlFndrInfo.fdType == 'APPL')
 
556
        buf->st_mode |= 0111;
 
557
      /* Fill in the sizes of data and resource forks. */
 
558
      buf->st_size = fpb->ioFlLgLen;
 
559
      buf->st_rsize = fpb->ioFlRLgLen;
 
560
    }
 
561
  /* Fill in various times. */
 
562
  buf->st_atime = fpb->ioFlCrDat;
 
563
  buf->st_mtime = fpb->ioFlMdDat;
 
564
  buf->st_ctime = fpb->ioFlCrDat;
 
565
  /* Set up an imitation inode number. */
 
566
  buf->st_ino = (unsigned short) fpb->ioDirID;
 
567
  /* Set up an imitation device. */
 
568
  GetVRefNum (buf->st_ino, &buf->st_dev);
 
569
  buf->st_uid = __uid;
 
570
  buf->st_gid = __gid;
 
571
/*  buf->st_FlFndrInfo = fpb->ioFlFndrInfo;  */
 
572
  return 0;
 
573
}
 
574
 
 
575
/* stat() sets up an empty dirid. */
 
576
 
 
577
int
 
578
stat (char *path, struct stat *buf)
 
579
{
 
580
  long rslt, errnum;
 
581
  char tmpname[256];
 
582
 
 
583
  mpwify_filename (path, tmpname);
 
584
  if (DebugPI)
 
585
    fprintf (stderr, "# stat (%s, %x)", tmpname, buf);
 
586
  PROGRESS (1);
 
587
  rslt = _stat (tmpname, 0L, buf);
 
588
  errnum = errno;
 
589
  if (DebugPI)
 
590
    {
 
591
      fprintf (stderr, " -> %d", rslt);
 
592
      if (rslt != 0)
 
593
        fprintf (stderr, " (errno is %d)", errnum);
 
594
      fprintf (stderr, "\n");
 
595
      fflush (stderr);
 
596
    }
 
597
  if (rslt != 0)
 
598
    errno = errnum;
 
599
  return rslt;
 
600
}
 
601
 
 
602
int
 
603
fstat (int fd, struct stat *buf)
 
604
{
 
605
  FCBPBRec fcb;
 
606
  FILE *fp;
 
607
  Str255 pathname;
 
608
  long dirid = 0L, temp;
 
609
  long rslt, errnum;
 
610
  short err;
 
611
 
 
612
  if (DebugPI < 0)
 
613
    DebugPI = (*(getenv ("DEBUG_PATHNAMES")) == '1' ? 1 : 0);
 
614
  if (DebugPI)
 
615
    fprintf (stderr, "# fstat (%d, %x)", fd, buf);
 
616
  PROGRESS (1);
 
617
  pathname[0] = 0;
 
618
#ifdef FIOFNAME
 
619
  /* Use an MPW-specific ioctl to get the pathname associated with
 
620
     the file descriptor.  */
 
621
  ioctl (fd, FIOFNAME, (long *) pathname); 
 
622
#else
 
623
  you lose
 
624
#endif
 
625
  if (DebugPI)
 
626
    fprintf (stderr, " (name is %s)", pathname);
 
627
  dirid = 0L /* fcb.ioFCBParID */ ;
 
628
  rslt = _stat ((char *) pathname, dirid, buf);
 
629
  errnum = errno;
 
630
  if (DebugPI)
 
631
    {
 
632
      fprintf (stderr, " -> %d", rslt);
 
633
      if (rslt != 0)
 
634
        fprintf (stderr, " (errno is %d)", errnum);
 
635
      fprintf (stderr, "\n");
 
636
      fflush (stderr);
 
637
    }
 
638
  if (rslt != 0)
 
639
    errno = errnum;
 
640
  return rslt;
 
641
}
 
642
 
 
643
#endif /* n USE_MW_HEADERS */
 
644
 
 
645
chdir ()
 
646
{
 
647
  errno = ENOSYS;
 
648
  return (-1);
 
649
}
 
650
 
 
651
char *
 
652
getcwd (char *buf, int size)
 
653
{
 
654
  if (buf == NULL)
 
655
    buf = (char *) malloc (size);
 
656
  strcpy(buf, ":");
 
657
  return buf;
 
658
}
 
659
 
 
660
/* This should probably be more elaborate for MPW. */
 
661
 
 
662
char *
 
663
getpwd ()
 
664
{
 
665
  return ":";
 
666
}
 
667
 
 
668
int
 
669
mpw_open (char *filename, int arg2, int arg3)
 
670
{
 
671
#undef open
 
672
  int fd, errnum = 0;
 
673
  char tmpname[256];
 
674
 
 
675
  mpwify_filename (filename, tmpname);
 
676
  fd = open (tmpname, arg2);
 
677
  errnum = errno;
 
678
 
 
679
  if (DebugPI)
 
680
    {
 
681
      fprintf (stderr, "# open (%s, %d, %d)", tmpname, arg2, arg3);
 
682
      fprintf (stderr, " -> %d", fd);
 
683
      if (fd == -1)
 
684
        fprintf (stderr, " (errno is %d)", errnum);
 
685
      fprintf (stderr, "\n");
 
686
    }
 
687
  if (fd == -1)
 
688
    errno = errnum;
 
689
  return fd;
 
690
}
 
691
 
 
692
int
 
693
mpw_access (char *filename, unsigned int cmd)
 
694
{
 
695
#undef access
 
696
 
 
697
  int rslt, errnum = 0;
 
698
  struct stat st;
 
699
  char tmpname[256];
 
700
 
 
701
  mpwify_filename (filename, tmpname);
 
702
  if (cmd & R_OK || cmd & X_OK)
 
703
    {
 
704
      rslt = stat (tmpname, &st);
 
705
      errnum = errno;
 
706
      if (rslt >= 0)
 
707
        {
 
708
          if ((((st.st_mode & 004) == 0) && (cmd & R_OK))
 
709
              || (((st.st_mode & 002) == 0) && (cmd & W_OK))
 
710
              || (((st.st_mode & 001) == 0) && (cmd & X_OK)))
 
711
            {
 
712
              rslt = -1;
 
713
              errnum = EACCES;
 
714
            }
 
715
        }
 
716
    }
 
717
  if (DebugPI)
 
718
    {
 
719
      fprintf (stderr, "# mpw_access (%s, %d)", tmpname, cmd);
 
720
      fprintf (stderr, " -> %d", rslt);
 
721
      if (rslt != 0)
 
722
        fprintf (stderr, " (errno is %d)", errnum);
 
723
      fprintf (stderr, "\n");
 
724
    }
 
725
  if (rslt != 0)
 
726
    errno = errnum;
 
727
  return rslt;
 
728
}
 
729
 
 
730
/* The MPW library creat() has no mode argument. */
 
731
 
 
732
int
 
733
mpw_creat (char *path, /* mode_t */ int mode)
 
734
{
 
735
#undef creat
 
736
 
 
737
#ifdef USE_MW_HEADERS
 
738
  return creat (path, mode);
 
739
#else
 
740
  return creat (path);
 
741
#endif
 
742
}
 
743
 
 
744
/* This is a hack to get control in an MPW tool before it crashes the
 
745
   machine.  */
 
746
 
 
747
mpw_special_init (name)
 
748
     char *name;
 
749
{
 
750
  if (strstr (name, "DEBUG"))
 
751
    DebugStr("\pat beginning of program");
 
752
}
 
753
 
 
754
static int current_umask;
 
755
 
 
756
int
 
757
umask(int mask)
 
758
{
 
759
  int oldmask = current_umask;
 
760
 
 
761
  current_umask = mask;
 
762
  return oldmask;
 
763
}
 
764
 
 
765
/* Cursor-spinning stuff that includes metering of spin rate and delays.  */
 
766
 
 
767
/* Nonzero when cursor spinning has been set up properly.  */
 
768
 
 
769
int cursor_inited;
 
770
 
 
771
/* Nonzero if spin should be measured and excessive delays reported.  */
 
772
 
 
773
int measure_spin;
 
774
 
 
775
/* Nonzero if spin histogram and rate data should be written out.  */
 
776
 
 
777
int dump_spin_data;
 
778
 
 
779
long warning_threshold = 400000;
 
780
 
 
781
long bucket_size = 1024;
 
782
 
 
783
long bucket_power = 10;
 
784
 
 
785
long numbuckets = 300;
 
786
 
 
787
int *delay_counts;
 
788
 
 
789
int overflow_count;
 
790
 
 
791
char *current_progress;
 
792
 
 
793
static UnsignedWide last_microseconds;
 
794
 
 
795
static char *last_spin_file = "";
 
796
 
 
797
static int last_spin_line;
 
798
 
 
799
void
 
800
warn_if_spin_delay (char *file, int line)
 
801
{
 
802
  long diff, ix;
 
803
  UnsignedWide now;
 
804
 
 
805
  Microseconds(&now);
 
806
 
 
807
  diff = now.lo - last_microseconds.lo;
 
808
 
 
809
  if (diff > warning_threshold)
 
810
    fprintf (stderr, "# %s: %ld.%06ld sec delay getting from %s:%d to %s:%d\n",
 
811
             (current_progress ? current_progress : ""),
 
812
             diff / 1000000, diff % 1000000,
 
813
             last_spin_file, last_spin_line, file, line);
 
814
  if (dump_spin_data)
 
815
    {
 
816
      if (diff >= 0)
 
817
        {
 
818
          ix = diff >> bucket_power;
 
819
          if (ix >= 0 && ix < numbuckets && delay_counts != NULL)
 
820
            ++delay_counts[ix];
 
821
          else
 
822
            ++overflow_count;
 
823
        }
 
824
      else
 
825
        fprintf (stderr, "raw diff is %ld (?)\n", diff);
 
826
    }
 
827
}
 
828
 
 
829
void
 
830
record_for_spin_delay (char *file, int line)
 
831
{
 
832
  Microseconds (&last_microseconds);
 
833
  last_spin_file = file;
 
834
  last_spin_line = line;
 
835
}
 
836
 
 
837
void
 
838
mpw_start_progress (char *str, int n, char *file, int line)
 
839
{
 
840
  int i;
 
841
  char *measure, *threshold;
 
842
 
 
843
  if (!cursor_inited)
 
844
    {
 
845
      InitCursorCtl (nil);
 
846
      cursor_inited = 1;
 
847
      record_for_spin_delay (file, line);
 
848
      measure = getenv ("MEASURE_SPIN");
 
849
      if (measure != NULL && measure[0] != '\0')
 
850
        {
 
851
          measure_spin = 1;
 
852
          if (strcmp (measure, "all") == 0)
 
853
            dump_spin_data = 1;
 
854
        }
 
855
      threshold = getenv ("SPIN_WARN_THRESHOLD");
 
856
      if (threshold != NULL && threshold[0] != '\0')
 
857
        warning_threshold = atol (threshold);
 
858
      if (dump_spin_data)
 
859
        {
 
860
          if (delay_counts == NULL)
 
861
            delay_counts = (int *) malloc (numbuckets * sizeof (int));
 
862
          for (i = 0; i < numbuckets; ++i)
 
863
            delay_counts[i] = 0;
 
864
          overflow_count = 0;
 
865
        }
 
866
    }
 
867
  current_progress = str;
 
868
 
 
869
  sys_nerr = errno_max ();
 
870
 
 
871
  mpw_special_init (str);
 
872
}
 
873
 
 
874
void
 
875
mpw_progress (int n)
 
876
{
 
877
  SpinCursor (32);
 
878
}
 
879
 
 
880
void
 
881
mpw_progress_measured (int n, char *file, int line)
 
882
{
 
883
  if (measure_spin)
 
884
    warn_if_spin_delay (file, line);
 
885
  SpinCursor (32);
 
886
  if (measure_spin)
 
887
    record_for_spin_delay (file, line);
 
888
}
 
889
 
 
890
void
 
891
mpw_end_progress (char *str, char *file, int line)
 
892
{
 
893
  long i, delay, count = 0, sum = 0, avgdelay, spinrate;
 
894
  long curpower = 0, curgroup = 0;
 
895
 
 
896
  /* Warn if it's been a while since the last spin.  */
 
897
  if (measure_spin)
 
898
    warn_if_spin_delay (file, line);
 
899
 
 
900
  /* Dump all the nonzero delay counts and an approximation of the delay.  */
 
901
  if (dump_spin_data && delay_counts != NULL)
 
902
    {
 
903
      for (i = 0; i < numbuckets; ++i)
 
904
        {
 
905
          delay = (i + 1) * bucket_size;
 
906
          sum += delay_counts[i] * (i + 1);
 
907
          count += delay_counts[i];
 
908
          if (delay <= (1 << curpower))
 
909
            {
 
910
              curgroup += delay_counts[i];
 
911
            }
 
912
          else
 
913
            {
 
914
              if (curgroup > 0)
 
915
                fprintf (stderr,
 
916
                         "# %s: %d delays between %ld.%06ld and %ld.%06ld sec\n",
 
917
                         (str ? str : ""),
 
918
                         curgroup,
 
919
                         (1 << curpower) / 1000000,
 
920
                         (1 << curpower) % 1000000,
 
921
                         (1 << (curpower + 1)) / 1000000,
 
922
                         (1 << (curpower + 1)) % 1000000);
 
923
              ++curpower;
 
924
              curgroup = 0;
 
925
            }
 
926
        }
 
927
      if (count > 0)
 
928
        {
 
929
          avgdelay = (sum * bucket_size) / count;
 
930
          spinrate = 1000000 / avgdelay;
 
931
          fprintf (stderr, "# %s: Average spin rate is %d times/sec\n",
 
932
                   (str ? str : ""), spinrate);
 
933
        }
 
934
    }
 
935
}
 
936
 
 
937
#ifdef PROGRESS_TEST
 
938
 
 
939
/* Test program.  */
 
940
 
 
941
main ()
 
942
{
 
943
  int i, j;
 
944
  double x = 1.0, y = 2.4;
 
945
  long start = Microseconds (), tm;  FIXME
 
946
 
 
947
  START_PROGRESS ("hi", 0);
 
948
 
 
949
  for (i = 0; i < 1000; ++i)
 
950
    {
 
951
      PROGRESS (1);
 
952
 
 
953
      for (j = 0; j < (i * 100); ++j)
 
954
        {
 
955
          x += (x * y) / j;
 
956
        }
 
957
    }
 
958
  
 
959
  END_PROGRESS ("hi");
 
960
  
 
961
  tm = Microseconds () - start;
 
962
 
 
963
  printf ("Total time is %d.%d secs\n", tm / 1000000, tm % 1000000);
 
964
}
 
965
 
 
966
#endif
 
967
 
 
968
#ifdef USE_MW_HEADERS
 
969
/* Empty definitions for Metrowerks' SIOUX console library. */
 
970
 
 
971
#ifndef __CONSOLE__
 
972
#include <console.h>
 
973
#endif
 
974
 
 
975
short
 
976
InstallConsole(short fd)
 
977
{
 
978
#pragma unused (fd)
 
979
        return 0;
 
980
}
 
981
 
 
982
void
 
983
RemoveConsole(void)
 
984
{
 
985
}
 
986
 
 
987
long
 
988
WriteCharsToConsole(char *buf, long n)
 
989
{
 
990
#pragma unused (buf, n)
 
991
        return 0;
 
992
}
 
993
 
 
994
long ReadCharsFromConsole(char *buf, long n)
 
995
{
 
996
#pragma unused (buf, n)
 
997
        return 0;
 
998
}
 
999
 
 
1000
extern char *
 
1001
__ttyname(long fd)
 
1002
{
 
1003
        static char *__devicename = "null device";
 
1004
 
 
1005
        if (fd >= 0 && fd <= 2)
 
1006
          return (__devicename);
 
1007
        return NULL;
 
1008
}
 
1009
 
 
1010
#endif