aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1999-09-06 22:32:26 +0000
committerRichard M. Stallman1999-09-06 22:32:26 +0000
commitc4ea52a64fc91467e6952d6dc32962b7ca7f940b (patch)
tree8d58def20a9e3c79f0af9795809555f49ef86b01 /src
parent162100b50740f3d5cbed0d7b8b18cfe098e3c5aa (diff)
downloademacs-c4ea52a64fc91467e6952d6dc32962b7ca7f940b.tar.gz
emacs-c4ea52a64fc91467e6952d6dc32962b7ca7f940b.zip
[macintosh] (stat, fstat, mkdir, rmdir, utime, access)
(open, creat, unlink, read, write, rename, fopen, pause, alarm) (signal, sleep, gmtime, localtime, ctime, time, index, mktemp) (getpwuid, getpwnam, dup, dup2, isatty, getgid, getegid, getuid) (geteuid, getpid, getenv, uname, opendir, closedir, readdir, getwd.): New functions, replacing POSIX features. [macintosh] (Mac2UnixPathname, Unix2MacPathname, CheckAlarm) (InitMyPasswd, GetTempDirName, mystrchr, mystrtok, mystrcpy): (InitEmacsPasswdDir, run_mac_command): New subroutines. [macintosh] (targetTicks, alarm_signal_func, myPasswdName) (myPasswd, emacsPasswdDir, emacsPasswd, myPasswdInited, mask) (myPasswdDir, TempDirName, sys_siglist): New variables. [macintosh] (execvp, wait, croak, fork, kill, sigsetmask) (sigblock, request_sigio, unrequest_sigio, setpgrp, pipe, symlink) (link, lstat, readlink, umask, chmod, sbrk, fsync, ioctl): Define empty stubs so Emacs will link.
Diffstat (limited to 'src')
-rw-r--r--src/sysdep.c1634
1 files changed, 1621 insertions, 13 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index 8c0e49231a4..92f12df5da0 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -30,6 +30,24 @@ Boston, MA 02111-1307, USA. */
30#include "blockinput.h" 30#include "blockinput.h"
31#undef NULL 31#undef NULL
32 32
33#ifdef macintosh
34#ifdef __MRC__
35__sigfun sys_signal (int signal, __sigfun signal_func);
36#elif __MWERKS__
37__signal_func_ptr sys_signal (int signal, __signal_func_ptr signal_func);
38#else
39You lose!!!
40#endif
41#ifndef subprocesses
42/* Nonzero means delete a process right away if it exits (process.c). */
43static int delete_exited_processes;
44#endif
45#ifndef HAVE_X_WINDOWS
46/* Search path for bitmap files (xfns.c). */
47Lisp_Object Vx_bitmap_file_path;
48#endif
49#endif /* macintosh */
50
33#define min(x,y) ((x) > (y) ? (y) : (x)) 51#define min(x,y) ((x) > (y) ? (y) : (x))
34 52
35/* In this file, open, read and write refer to the system calls, 53/* In this file, open, read and write refer to the system calls,
@@ -152,7 +170,7 @@ extern int errno;
152#undef TIOCSWINSZ 170#undef TIOCSWINSZ
153#endif 171#endif
154 172
155#if defined(USG) || defined(DGUX) 173#if defined (USG) || defined (DGUX)
156#include <sys/utsname.h> 174#include <sys/utsname.h>
157#include <string.h> 175#include <string.h>
158#ifndef MEMORY_IN_STRING_H 176#ifndef MEMORY_IN_STRING_H
@@ -709,7 +727,7 @@ sys_suspend ()
709 } 727 }
710 return -1; 728 return -1;
711#else 729#else
712#if defined(SIGTSTP) && !defined(MSDOS) 730#if defined (SIGTSTP) && !defined (MSDOS)
713 731
714 { 732 {
715 int pgrp = EMACS_GETPGRP (0); 733 int pgrp = EMACS_GETPGRP (0);
@@ -738,6 +756,9 @@ sys_suspend ()
738void 756void
739sys_subshell () 757sys_subshell ()
740{ 758{
759#ifdef macintosh
760 error ("Can't spawn subshell");
761#else
741#ifndef VMS 762#ifndef VMS
742#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */ 763#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
743 int st; 764 int st;
@@ -854,6 +875,7 @@ sys_subshell ()
854 restore_signal_handlers (saved_handlers); 875 restore_signal_handlers (saved_handlers);
855 synch_process_alive = 0; 876 synch_process_alive = 0;
856#endif /* !VMS */ 877#endif /* !VMS */
878#endif /* !macintosh */
857} 879}
858 880
859static void 881static void
@@ -971,11 +993,11 @@ request_sigio ()
971 if (read_socket_hook) 993 if (read_socket_hook)
972 return; 994 return;
973 995
974 sigemptyset(&st); 996 sigemptyset (&st);
975 sigaddset(&st, SIGIO); 997 sigaddset (&st, SIGIO);
976 ioctl (input_fd, FIOASYNC, &on); 998 ioctl (input_fd, FIOASYNC, &on);
977 interrupts_deferred = 0; 999 interrupts_deferred = 0;
978 sigprocmask(SIG_UNBLOCK, &st, (sigset_t *)0); 1000 sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
979} 1001}
980 1002
981void 1003void
@@ -1139,7 +1161,7 @@ emacs_set_tty (fd, settings, flushp)
1139 int i; 1161 int i;
1140 /* We have those nifty POSIX tcmumbleattr functions. 1162 /* We have those nifty POSIX tcmumbleattr functions.
1141 William J. Smith <wjs@wiis.wang.com> writes: 1163 William J. Smith <wjs@wiis.wang.com> writes:
1142 "POSIX 1003.1 defines tcsetattr() to return success if it was 1164 "POSIX 1003.1 defines tcsetattr to return success if it was
1143 able to perform any of the requested actions, even if some 1165 able to perform any of the requested actions, even if some
1144 of the requested actions could not be performed. 1166 of the requested actions could not be performed.
1145 We must read settings back to ensure tty setup properly. 1167 We must read settings back to ensure tty setup properly.
@@ -1168,7 +1190,7 @@ emacs_set_tty (fd, settings, flushp)
1168 && new.c_oflag == settings->main.c_oflag 1190 && new.c_oflag == settings->main.c_oflag
1169 && new.c_cflag == settings->main.c_cflag 1191 && new.c_cflag == settings->main.c_cflag
1170 && new.c_lflag == settings->main.c_lflag 1192 && new.c_lflag == settings->main.c_lflag
1171 && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0) 1193 && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
1172 break; 1194 break;
1173 else 1195 else
1174 continue; 1196 continue;
@@ -1264,6 +1286,26 @@ init_sys_modes ()
1264{ 1286{
1265 struct emacs_tty tty; 1287 struct emacs_tty tty;
1266 1288
1289#ifdef macintosh
1290 Vwindow_system = intern ("mac");
1291 Vwindow_system_version = make_number (1);
1292
1293/* cus-start.el complains if delete-exited-processes and x-bitmap-file-path not defined */
1294#ifndef subprocesses
1295 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
1296 "*Non-nil means delete processes immediately when they exit.\n\
1297nil means don't delete them until `list-processes' is run.");
1298 delete_exited_processes = 0;
1299#endif
1300
1301#ifndef HAVE_X_WINDOWS
1302 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
1303 "List of directories to search for bitmap files for X.");
1304 Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
1305#endif
1306
1307#endif /* not macintosh */
1308
1267#ifdef VMS 1309#ifdef VMS
1268#if 0 1310#if 0
1269 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */ 1311 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
@@ -2196,7 +2238,7 @@ start_of_data ()
2196 */ 2238 */
2197 extern char **environ; 2239 extern char **environ;
2198 2240
2199 return((char *) &environ); 2241 return ((char *) &environ);
2200#else 2242#else
2201 extern int data_start; 2243 extern int data_start;
2202 return ((char *) &data_start); 2244 return ((char *) &data_start);
@@ -3485,7 +3527,7 @@ char *sys_siglist[NSIG + 1] =
3485 3527
3486#include <dirent.h> 3528#include <dirent.h>
3487 3529
3488#if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR) 3530#if defined (BROKEN_CLOSEDIR) || !defined (HAVE_CLOSEDIR)
3489 3531
3490int 3532int
3491closedir (dirp) 3533closedir (dirp)
@@ -3730,7 +3772,7 @@ mkdir (dpath, dmode)
3730 */ 3772 */
3731 status = umask (0); /* Get current umask */ 3773 status = umask (0); /* Get current umask */
3732 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */ 3774 status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
3733 fd = sys_open("/dev/null", 2); 3775 fd = sys_open ("/dev/null", 2);
3734 if (fd >= 0) 3776 if (fd >= 0)
3735 { 3777 {
3736 dup2 (fd, 0); 3778 dup2 (fd, 0);
@@ -3776,7 +3818,7 @@ rmdir (dpath)
3776 return (-1); /* Errno is set already */ 3818 return (-1); /* Errno is set already */
3777 3819
3778 case 0: /* Child process */ 3820 case 0: /* Child process */
3779 fd = sys_open("/dev/null", 2); 3821 fd = sys_open ("/dev/null", 2);
3780 if (fd >= 0) 3822 if (fd >= 0)
3781 { 3823 {
3782 dup2 (fd, 0); 3824 dup2 (fd, 0);
@@ -5099,7 +5141,7 @@ hft_init ()
5099 there's no way to determine the old mapping, so in reset_sys_modes 5141 there's no way to determine the old mapping, so in reset_sys_modes
5100 we need to assume that the normal map had been present. Of course, this 5142 we need to assume that the normal map had been present. Of course, this
5101 code also doesn't help if on a terminal emulator which doesn't understand 5143 code also doesn't help if on a terminal emulator which doesn't understand
5102 HFT VTD's. */ 5144 HFT VTD's. */
5103 { 5145 {
5104 struct hfbuf buf; 5146 struct hfbuf buf;
5105 struct hfkeymap keymap; 5147 struct hfkeymap keymap;
@@ -5130,7 +5172,7 @@ hft_init ()
5130 line_ins_del_ok = char_ins_del_ok = 0; 5172 line_ins_del_ok = char_ins_del_ok = 0;
5131} 5173}
5132 5174
5133/* Reset the rubout key to backspace. */ 5175/* Reset the rubout key to backspace. */
5134 5176
5135void 5177void
5136hft_reset () 5178hft_reset ()
@@ -5277,3 +5319,1569 @@ bcmp (b1, b2, length) /* This could be a macro! */
5277} 5319}
5278#endif /* no bcmp */ 5320#endif /* no bcmp */
5279#endif /* not BSTRING */ 5321#endif /* not BSTRING */
5322
5323/* All the Macintosh stuffs go here */
5324
5325#ifdef macintosh
5326
5327#include <Files.h>
5328#include <MacTypes.h>
5329#include <TextUtils.h>
5330#include <Folders.h>
5331
5332#include <dirent.h>
5333#include <sys/stat.h>
5334#include <string.h>
5335#include <pwd.h>
5336#include <sys/param.h>
5337
5338/* Convert a Mac pathname to Unix form. A Mac full pathname is one
5339 that does not begin with a ':' and contains at least one ':'. A Mac
5340 full pathname causes an '/' to be prepended to the Unix pathname.
5341 The algorithm for the rest of the pathname is as follows:
5342 For each segment between two ':',
5343 if it is non-null, copy as is and then add a '/' at the end,
5344 otherwise, insert a "../" into the Unix pathname.
5345 Returns 1 if successful; 0 if fails. */
5346
5347int
5348Mac2UnixPathname (const char *mfn, char *ufn, int ufnbuflen)
5349{
5350 const char *p, *q, *pe;
5351
5352 strcpy (ufn, "");
5353
5354 if (*mfn == '\0')
5355 return 1;
5356
5357 p = strchr (mfn, ':');
5358 if (p != 0 && p != mfn) /* full pathname */
5359 strcat (ufn, "/");
5360
5361 p = mfn;
5362 if (*p == ':')
5363 p++;
5364
5365 pe = mfn + strlen (mfn);
5366 while (p < pe)
5367 {
5368 q = strchr (p, ':');
5369 if (q)
5370 {
5371 if (q == p)
5372 { /* two consecutive ':' */
5373 if (strlen (ufn) + 3 >= ufnbuflen)
5374 return 0;
5375 strcat (ufn, "../");
5376 }
5377 else
5378 {
5379 if (strlen (ufn) + (q - p) + 1 >= ufnbuflen)
5380 return 0;
5381 strncat (ufn, p, q - p);
5382 strcat (ufn, "/");
5383 }
5384 p = q + 1;
5385 }
5386 else
5387 {
5388 if (strlen (ufn) + (pe - p) >= ufnbuflen)
5389 return 0;
5390 strncat (ufn, p, pe - p); /* no separator for last one */
5391 p = pe;
5392 }
5393 }
5394
5395 return 1;
5396}
5397
5398extern char *GetTempDirName ();
5399
5400/* Convert a Unix pathname to Mac form. Approximately reverse of the
5401 above in algorithm. */
5402int
5403Unix2MacPathname (const char *ufn, char *mfn, int mfnbuflen)
5404{
5405 const char *p, *q, *pe;
5406 char expandedPathname[MAXPATHLEN+1];
5407
5408 strcpy (mfn, "");
5409
5410 if (*ufn == '\0')
5411 return 1;
5412
5413 p = ufn;
5414
5415 /* Check for and handle volume names. Last comparison: strangely
5416 somewhere `/.emacs' is passed. A temporary fix for now. */
5417 if (*p == '/' && strchr (p+1, '/') == NULL && strcmp (p, "/.emacs") != 0)
5418 {
5419 if (strlen (p) + 1 > mfnbuflen)
5420 return 0;
5421 strcpy (mfn, p+1);
5422 strcat (mfn, ":");
5423 return 1;
5424 }
5425
5426 if (strncmp (p, "~emacs/", 7) == 0)
5427 { /* expand to emacs dir found by InitEmacsPasswdDir */
5428 struct passwd *pw = getpwnam ("emacs");
5429 p += 7;
5430 if (strlen (pw->pw_dir) + strlen (p) > MAXPATHLEN)
5431 return 0;
5432 strcpy (expandedPathname, pw->pw_dir);
5433 strcat (expandedPathname, p);
5434 p = expandedPathname;
5435 /* Now p points to the pathname with emacs dir prefix. */
5436 }
5437 else if (strncmp (p, "/tmp/", 5) == 0)
5438 {
5439 char *t = GetTempDirName ();
5440 p += 5;
5441 if (strlen (t) + strlen (p) > MAXPATHLEN)
5442 return 0;
5443 strcpy (expandedPathname, t);
5444 strcat (expandedPathname, p);
5445 p = expandedPathname;
5446 /* Now p points to the pathname with emacs dir prefix. */
5447 }
5448 else if (*p != '/') /* relative pathname */
5449 strcat (mfn, ":");
5450
5451 if (*p == '/')
5452 p++;
5453
5454 pe = p + strlen (p);
5455 while (p < pe)
5456 {
5457 q = strchr (p, '/');
5458 if (q)
5459 {
5460 if (q - p == 2 && *p == '.' && *(p+1) == '.')
5461 {
5462 if (strlen (mfn) + 1 >= mfnbuflen)
5463 return 0;
5464 strcat (mfn, ":");
5465 }
5466 else
5467 {
5468 if (strlen (mfn) + (q - p) + 1 >= mfnbuflen)
5469 return 0;
5470 strncat (mfn, p, q - p);
5471 strcat (mfn, ":");
5472 }
5473 p = q + 1;
5474 }
5475 else
5476 {
5477 if (strlen (mfn) + (pe - p) >= mfnbuflen)
5478 return 0;
5479 strncat (mfn, p, pe - p);
5480 p = pe;
5481 }
5482 }
5483
5484 return 1;
5485}
5486
5487/* The following functions with "sys_" prefix are stubs to Unix
5488 functions that have already been implemented by CW or MPW. The
5489 calls to them in Emacs source course are #define'd to call the sys_
5490 versions by the header files s-mac.h. In these stubs pathnames are
5491 converted between their Unix and Mac forms. */
5492/* Unix Epoch is Jan 1, 1970 while Mac Epoch is Jan 1, 1904: 66 years
5493 + 17 leap days */
5494#define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
5495
5496/* CW Epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not a leap
5497 year! */
5498#define CW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
5499
5500/* Define our own stat function for both MrC and CW. The reason for
5501 doing this: "stat" is both the name of a struct and function name:
5502 can't use the same trick like that for sys_open, sys_close, etc. to
5503 redirect Emacs's calls to our own version that converts Unix style
5504 filenames to Mac style filename because all sorts of compilation
5505 errors will be generated if stat is #define'd to be sys_stat. */
5506
5507int
5508stat (const char *path, struct stat *buf)
5509{
5510 char MacPathname[MAXPATHLEN+1];
5511 CInfoPBRec cipb;
5512
5513 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5514 return -1;
5515
5516 c2pstr (MacPathname);
5517 cipb.hFileInfo.ioNamePtr = MacPathname;
5518 cipb.hFileInfo.ioVRefNum = 0;
5519 cipb.hFileInfo.ioDirID = 0;
5520 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
5521
5522 errno = PBGetCatInfo (&cipb, false);
5523 if (errno == -43) /* -43: fnfErr defined in Errors.h */
5524 errno = ENOENT;
5525 if (errno != noErr)
5526 return -1;
5527
5528 if (cipb.hFileInfo.ioFlAttrib & 0x10)
5529 { /* bit 4 = 1 for directories */
5530 buf->st_mode = S_IFDIR | S_IREAD | S_IEXEC;
5531 if (!(cipb.hFileInfo.ioFlAttrib & 0x1)) /* bit 1 = 1 for locked files/directories */
5532 buf->st_mode |= S_IWRITE;
5533 buf->st_ino = cipb.dirInfo.ioDrDirID;
5534 buf->st_dev = cipb.dirInfo.ioVRefNum;
5535 buf->st_size = cipb.dirInfo.ioDrNmFls; /* size of dir = number of files and dirs */
5536 buf->st_atime = buf->st_mtime = cipb.dirInfo.ioDrMdDat - MAC_UNIX_EPOCH_DIFF;
5537 buf->st_ctime = cipb.dirInfo.ioDrCrDat - MAC_UNIX_EPOCH_DIFF;
5538 }
5539 else
5540 {
5541 buf->st_mode = S_IFREG | S_IREAD;
5542 if (!(cipb.hFileInfo.ioFlAttrib & 0x1)) /* bit 1 = 1 for locked files/directories */
5543 buf->st_mode |= S_IWRITE;
5544 if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
5545 buf->st_mode |= S_IEXEC;
5546 buf->st_ino = cipb.hFileInfo.ioDirID;
5547 buf->st_dev = cipb.hFileInfo.ioVRefNum;
5548 buf->st_size = cipb.hFileInfo.ioFlLgLen;
5549 buf->st_atime = buf->st_mtime = cipb.hFileInfo.ioFlMdDat - MAC_UNIX_EPOCH_DIFF;
5550 buf->st_ctime = cipb.hFileInfo.ioFlCrDat - MAC_UNIX_EPOCH_DIFF;
5551 }
5552 buf->st_nlink = 1;
5553 buf->st_uid = getuid ();
5554 buf->st_gid = getgid ();
5555 buf->st_rdev = 0;
5556
5557 return 0;
5558}
5559
5560#if __MRC__
5561
5562/* CW defines fstat in stat.mac.c while MPW does not provide this
5563 function. Without the information of how to get from a file
5564 descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
5565 to implement this function. Fortunately, there is only one place
5566 where this function is called in our configuration: in fileio.c,
5567 where only the st_dev and st_ino fields are used to determine
5568 whether two fildes point to different i-nodes to prevent copying
5569 a file onto itself equal. What we have here probably needs
5570 improvement. */
5571int
5572fstat (int fildes, struct stat *buf)
5573{
5574 buf->st_dev = 0;
5575 buf->st_ino = fildes;
5576 return 0; /* success */
5577}
5578
5579#endif /* __MRC__ */
5580
5581/* From Think Reference code example */
5582int
5583mkdir (const char *dirname, int mode)
5584{
5585#pragma unused (mode)
5586
5587 HFileParam hfpb;
5588 char MacPathname[MAXPATHLEN+1];
5589
5590 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
5591 return -1;
5592
5593 c2pstr (MacPathname);
5594 hfpb.ioNamePtr = MacPathname;
5595 hfpb.ioVRefNum = 0; /*ignored unless name is invalid */
5596 hfpb.ioDirID = 0; /*parent is the root */
5597
5598 /* Just return the Mac OSErr code for now. */
5599 errno = PBDirCreate ((HParmBlkPtr) &hfpb, false);
5600 return errno == noErr ? 0 : -1;
5601}
5602
5603int
5604rmdir (const char *dirname)
5605{
5606 HFileParam hfpb;
5607 char MacPathname[MAXPATHLEN+1];
5608
5609 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
5610 return -1;
5611
5612 c2pstr (MacPathname);
5613 hfpb.ioNamePtr = MacPathname;
5614 hfpb.ioVRefNum = 0; /*ignored unless name is invalid */
5615 hfpb.ioDirID = 0; /*parent is the root */
5616
5617 errno = PBHDelete ((HParmBlkPtr) &hfpb, false);
5618 return errno == noErr ? 0 : -1;
5619}
5620
5621#ifdef __MRC__
5622
5623/* No implementation yet. */
5624int
5625execvp (const char *path, ...)
5626{
5627 return -1;
5628}
5629
5630#endif /* __MRC__ */
5631
5632int
5633utime (const char *path, const struct utimbuf *times)
5634{
5635 char MacPathname[MAXPATHLEN+1];
5636 CInfoPBRec cipb;
5637
5638 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5639 return -1;
5640
5641 c2pstr (MacPathname);
5642 cipb.hFileInfo.ioNamePtr = MacPathname;
5643 cipb.hFileInfo.ioVRefNum = 0;
5644 cipb.hFileInfo.ioDirID = 0;
5645 /* Set to 0 to get information about specific dir or file. */
5646 cipb.hFileInfo.ioFDirIndex = 0;
5647
5648 errno = PBGetCatInfo (&cipb, false);
5649 if (errno != noErr)
5650 return -1;
5651
5652 if (cipb.hFileInfo.ioFlAttrib & 0x10)
5653 { /* bit 4 = 1 for directories */
5654 if (times)
5655 cipb.dirInfo.ioDrMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
5656 else
5657 GetDateTime (&cipb.dirInfo.ioDrMdDat);
5658 }
5659 else
5660 {
5661 if (times)
5662 cipb.hFileInfo.ioFlMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
5663 else
5664 GetDateTime (&cipb.hFileInfo.ioFlMdDat);
5665 }
5666
5667 errno = PBSetCatInfo (&cipb, false);
5668 return errno == noErr ? 0 : -1;
5669}
5670
5671#define F_OK 0
5672#define X_OK 1
5673#define W_OK 2
5674
5675/* Like stat, but test for access mode in hfpb.ioFlAttrib. */
5676int
5677access (const char *path, int mode)
5678{
5679 char MacPathname[MAXPATHLEN+1];
5680 CInfoPBRec cipb;
5681
5682 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5683 return -1;
5684
5685 c2pstr (MacPathname);
5686 cipb.hFileInfo.ioNamePtr = MacPathname;
5687 cipb.hFileInfo.ioVRefNum = 0;
5688 cipb.hFileInfo.ioDirID = 0;
5689 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
5690
5691 errno = PBGetCatInfo (&cipb, false);
5692 if (errno != noErr)
5693 return -1;
5694
5695 if (mode == F_OK) /* got this far, file exists */
5696 return 0;
5697
5698 if (mode & X_OK)
5699 if (cipb.hFileInfo.ioFlAttrib & 0x10) /* path refers to a directory */
5700 return 0;
5701 else
5702 {
5703 if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
5704 return 0;
5705 else
5706 return -1;
5707 }
5708
5709 if (mode & W_OK)
5710 return (cipb.hFileInfo.ioFlAttrib & 0x1) ? -1 : 0; /* don't allow if lock bit on */
5711
5712 return -1;
5713}
5714
5715#define DEV_NULL_FD 0x10000
5716
5717#undef open
5718int
5719sys_open (const char *path, int oflag)
5720{
5721 char MacPathname[MAXPATHLEN+1];
5722
5723 if (strcmp (path, "/dev/null") == 0)
5724 return DEV_NULL_FD; /* some bogus fd to be ignored in write */
5725
5726 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5727 return -1;
5728 else
5729 return open (MacPathname, oflag);
5730}
5731
5732#undef creat
5733int
5734sys_creat (const char *path, mode_t mode)
5735{
5736 char MacPathname[MAXPATHLEN+1];
5737
5738 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5739 return -1;
5740 else
5741 return creat (MacPathname, mode);
5742}
5743
5744#undef unlink
5745int
5746sys_unlink (const char *path)
5747{
5748 char MacPathname[MAXPATHLEN+1];
5749
5750 if (Unix2MacPathname (path, MacPathname, MAXPATHLEN+1) == 0)
5751 return -1;
5752 else
5753 return unlink (MacPathname);
5754}
5755
5756#undef read
5757int
5758sys_read (int fildes, char *buf, int count)
5759{
5760 if (fildes == 0)
5761 { /* if stdin, call (non-echoing) "getch" in console.h */
5762 if (MacKeyPending ())
5763 { /* don't wait for a key if none has been pressed */
5764 *buf = MacGetChar ();
5765 return 1;
5766 }
5767 else
5768 return 0;
5769 }
5770 else
5771 return read (fildes, buf, count);
5772}
5773
5774#undef write
5775int
5776sys_write (int fildes, char *buf, int count)
5777{
5778 if (fildes == DEV_NULL_FD)
5779 return count;
5780 else
5781 return write (fildes, buf, count);
5782}
5783
5784#undef rename
5785int
5786sys_rename (const char * old_name, const char * new_name)
5787{
5788 char MacOldName[MAXPATHLEN+1], MacNewName[MAXPATHLEN+1];
5789
5790 if (strcmp (old_name, new_name) == 0)
5791 return 0;
5792
5793 if (Unix2MacPathname (old_name, MacOldName, MAXPATHLEN+1) == 0)
5794 return 1;
5795
5796 if (Unix2MacPathname (new_name, MacNewName, MAXPATHLEN+1) == 0)
5797 return 1;
5798
5799 return rename (MacOldName, MacNewName);
5800}
5801
5802#undef fopen
5803extern FILE *fopen (const char *name, const char *mode);
5804FILE
5805sys_fopen (const char *name, const char *mode)
5806{
5807 char MacPathname[MAXPATHLEN+1];
5808
5809 if (Unix2MacPathname (name, MacPathname, MAXPATHLEN+1) == 0)
5810 return 0;
5811 else
5812 return fopen (MacPathname, mode);
5813}
5814
5815#include <Events.h>
5816
5817long targetTicks = 0;
5818
5819#ifdef __MRC__
5820__sigfun alarm_signal_func = (__sigfun) 0;
5821#elif __MWERKS__
5822__signal_func_ptr alarm_signal_func = (__signal_func_ptr) 0;
5823#else
5824You lose!!!
5825#endif
5826
5827/* These functions simulate SIG_ALRM. The stub for function signal
5828 stores the signal handler function in alarm_signal_func if a
5829 SIG_ALRM is encountered. CheckAlarm is called in mac_read_socket,
5830 which emacs calls periodically. A pending alarm is represented by
5831 a non-zero targetTicks value. CheckAlarm calls the handler
5832 function pointed to by alarm_signal_func if one has been set up and
5833 an alarm is pending. */
5834void
5835CheckAlarm ()
5836{
5837 if (targetTicks && TickCount () > targetTicks)
5838 {
5839 targetTicks = 0;
5840 if (alarm_signal_func)
5841 (*alarm_signal_func)(SIGALRM);
5842 }
5843}
5844
5845/* Called in sys_select to wait for an alarm signal to arrive. */
5846int
5847pause ()
5848{
5849 unsigned long finalTick;
5850
5851 if (!targetTicks) /* no alarm pending */
5852 return -1;
5853
5854 while (TickCount () <= targetTicks)
5855 Delay (1UL, &finalTick); /* wait for 1/60 second before trying again */
5856
5857 targetTicks = 0;
5858 if (alarm_signal_func)
5859 (*alarm_signal_func)(SIGALRM);
5860
5861 return 0;
5862}
5863
5864int
5865alarm (int seconds)
5866{
5867 long remaining = targetTicks ? (TickCount () - targetTicks) / 60 : 0;
5868
5869 targetTicks = seconds ? TickCount () + 60 * seconds : 0;
5870
5871 return (remaining < 0) ? 0 : (unsigned int) remaining;
5872}
5873
5874#undef signal
5875#ifdef __MRC__
5876extern __sigfun signal (int signal, __sigfun signal_func);
5877__sigfun
5878sys_signal (int signal_num, __sigfun signal_func)
5879#elif __MWERKS__
5880extern __signal_func_ptr signal (int signal, __signal_func_ptr signal_func);
5881__signal_func_ptr
5882sys_signal (int signal_num, __signal_func_ptr signal_func)
5883#else
5884 You lose!!!
5885#endif
5886{
5887 if (signal_num != SIGALRM)
5888 return signal (signal_num, signal_func);
5889 else
5890 {
5891#ifdef __MRC__
5892 __sigfun old_signal_func;
5893#elif __MWERKS__
5894 __signal_func_ptr old_signal_func;
5895#else
5896 You lose!!!
5897#endif
5898 old_signal_func = alarm_signal_func;
5899 alarm_signal_func = signal_func;
5900 return old_signal_func;
5901 }
5902}
5903
5904/* The time functions adjust time values according to the difference
5905 between the Unix and CW epoches. */
5906
5907#undef gmtime
5908extern struct tm *gmtime (const time_t *);
5909struct tm
5910sys_gmtime (const time_t *timer)
5911{
5912 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5913
5914 return gmtime (&unixTime);
5915}
5916
5917#undef localtime
5918extern struct tm *localtime (const time_t *);
5919struct tm *
5920sys_localtime (const time_t *timer)
5921{
5922 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5923
5924 return localtime (&unixTime);
5925}
5926
5927#undef ctime
5928extern char *ctime (const time_t *);
5929char *
5930sys_ctime (const time_t *timer)
5931{
5932 time_t unixTime = *timer + CW_UNIX_EPOCH_DIFF;
5933
5934 return ctime (&unixTime);
5935}
5936
5937#undef time
5938extern time_t time (time_t *);
5939time_t
5940sys_time (time_t *timer)
5941{
5942 time_t macTime = time (NULL) - CW_UNIX_EPOCH_DIFF;
5943
5944 if (timer)
5945 *timer = macTime;
5946
5947 return macTime;
5948}
5949
5950/* no subprocesses, empty wait */
5951int
5952wait (int pid)
5953{
5954 return 0;
5955}
5956
5957void
5958croak (char *badfunc)
5959{
5960 printf ("%s not yet implemented\r\n", badfunc);
5961 exit (1);
5962}
5963
5964char *
5965index (const char * str, int chr)
5966{
5967 return strchr (str, chr);
5968}
5969
5970char *e[] = { 0 };
5971char **environ = &e[0];
5972
5973char *
5974mktemp (char *template)
5975{
5976 int len, k;
5977 static seqnum = 0;
5978
5979 len = strlen (template);
5980 k = len - 1;
5981 while (k >= 0 && template[k] == 'X')
5982 k--;
5983
5984 k++; /* make k index of first 'X' */
5985
5986 if (k < len)
5987 {
5988 /* Zero filled, number of digits equal to the number of X's. */
5989 sprintf (&template[k], "%0*d", len-k, seqnum++);
5990
5991 return template;
5992 }
5993 else
5994 return 0;
5995}
5996
5997/* Emulate getpwuid, getpwnam and others. */
5998
5999#define PASSWD_FIELD_SIZE 256
6000
6001static char myPasswdName[PASSWD_FIELD_SIZE];
6002static char myPasswdDir[MAXPATHLEN+1];
6003
6004static struct passwd myPasswd =
6005{
6006 myPasswdName,
6007 myPasswdDir,
6008};
6009
6010/* Initialized by main () in macterm.c to pathname of emacs directory. */
6011char emacsPasswdDir[MAXPATHLEN+1];
6012
6013void
6014InitEmacsPasswdDir ()
6015{
6016 int found = false;
6017
6018 if (getwd (emacsPasswdDir) && getwd (myPasswdDir))
6019 {
6020 /* Need pathname of first ancestor that begins with `emacs' since
6021 Mac emacs application is somewhere in the emacs-20.3 tree. */
6022 int len = strlen (emacsPasswdDir);
6023 /* J points to the "/" following the directory name being compared. */
6024 int j = len - 1;
6025 int i = j - 1;
6026 while (i >= 0 && !found)
6027 {
6028 while (i >= 0 && emacsPasswdDir[i] != '/')
6029 i--;
6030 if (emacsPasswdDir[i] == '/' && i+5 < len)
6031 found = (strncmp (&(emacsPasswdDir[i+1]), "emacs", 5) == 0);
6032 if (found)
6033 emacsPasswdDir[j+1] = '\0';
6034 else
6035 {
6036 j = i;
6037 i = j - 1;
6038 }
6039 }
6040 }
6041
6042 if (!found)
6043 { /* setting to "/" probably won't work,
6044 but set it to something anyway. */
6045 strcpy (emacsPasswdDir, "/");
6046 strcpy (myPasswdDir, "/");
6047 }
6048}
6049
6050static struct passwd emacsPasswd =
6051{
6052 "emacs",
6053 emacsPasswdDir,
6054};
6055
6056static int myPasswdInited = 0;
6057
6058static void
6059InitMyPasswd ()
6060{
6061 char **ownerName;
6062
6063 /* Note: myPasswdDir initialized in InitEmacsPasswdDir to directory
6064 where Emacs was started. */
6065
6066 ownerName = (char **) GetResource ('STR ',-16096);
6067 if (ownerName)
6068 {
6069 HLock (ownerName);
6070 BlockMove ((unsigned char *) *ownerName,
6071 (unsigned char *) myPasswdName, *ownerName[0] + 1);
6072 HUnlock (ownerName);
6073 p2cstr ((unsigned char *) myPasswdName);
6074 }
6075 else
6076 myPasswdName[0] = 0;
6077}
6078
6079struct passwd *
6080getpwuid (uid_t uid)
6081{
6082 if (!myPasswdInited)
6083 {
6084 InitMyPasswd ();
6085 myPasswdInited = 1;
6086 }
6087
6088 return &myPasswd;
6089}
6090
6091struct passwd *
6092getpwnam (const char *name)
6093{
6094 if (strcmp (name, "emacs") == 0)
6095 return &emacsPasswd;
6096
6097 if (!myPasswdInited)
6098 {
6099 InitMyPasswd ();
6100 myPasswdInited = 1;
6101 }
6102
6103 return &myPasswd;
6104}
6105
6106/* The functions fork, kill, sigsetmask, sigblock, request_sigio,
6107 setpgrp, setpriority, and unrequest_sigio are defined to be empty
6108 as in msdos.c. */
6109
6110int
6111fork ()
6112{
6113 return -1;
6114}
6115
6116int
6117kill (int x, int y)
6118{
6119 return -1;
6120}
6121
6122int
6123sigsetmask (int x)
6124{
6125 return 0;
6126}
6127
6128int
6129sigblock (int mask)
6130{
6131 return 0;
6132}
6133
6134void
6135request_sigio (void)
6136{
6137}
6138
6139int
6140setpgrp ()
6141{
6142 return 0;
6143}
6144
6145void
6146unrequest_sigio (void)
6147{
6148}
6149
6150/* djgpp does not implement pipe either. */
6151int
6152pipe (int _fildes[2])
6153{
6154 errno = EACCES;
6155 return -1;
6156}
6157
6158/* Hard and symbolic links. */
6159int
6160symlink (const char *name1, const char *name2)
6161{
6162 errno = ENOENT;
6163 return -1;
6164}
6165
6166int
6167link (const char *name1, const char *name2)
6168{
6169 errno = ENOENT;
6170 return -1;
6171}
6172
6173int
6174lstat (const char *path, struct stat *sb)
6175{
6176 return stat (path, sb);
6177}
6178
6179int
6180readlink (const char *path, char *buf, int bufsiz)
6181{
6182 errno = ENOENT;
6183 return -1;
6184}
6185
6186mode_t
6187umask (mode_t numask)
6188{
6189 static mode_t mask = 022;
6190 mode_t oldmask = mask;
6191 mask = numask;
6192 return oldmask;
6193}
6194
6195int
6196chmod (const char *path, mode_t mode)
6197{
6198 /* say it always succeed for now */
6199 return 0;
6200}
6201
6202int
6203dup (int oldd)
6204{
6205#ifdef __MRC__
6206 return fcntl (oldd, F_DUPFD, 0);
6207#elif __MWERKS__
6208 /* current implementation of fcntl in fcntl.mac.c simply returns old
6209 descriptor */
6210 return fcntl (oldd, F_DUPFD);
6211#else
6212You lose!!!
6213#endif
6214}
6215
6216/* This is from the original sysdep.c. Emulate BSD dup2. First close
6217 newd if it already exists. Then, attempt to dup oldd. If not
6218 successful, call dup2 recursively until we are, then close the
6219 unsuccessful ones. */
6220int
6221dup2 (int oldd, int newd)
6222{
6223 int fd, ret;
6224
6225 close (newd);
6226
6227 fd = dup (oldd);
6228 if (fd == -1)
6229 return -1;
6230 if (fd == newd)
6231 return newd;
6232 ret = dup2 (oldd, newd);
6233 close (fd);
6234 return ret;
6235}
6236
6237/* let it fail for now */
6238char *
6239sbrk (int incr)
6240{
6241 return (char *) -1;
6242}
6243
6244int
6245fsync (int fd)
6246{
6247 return 0;
6248}
6249
6250int
6251ioctl (int d, int request, void *argp)
6252{
6253 return -1;
6254}
6255
6256#ifdef __MRC__
6257int
6258isatty (int fildes)
6259{
6260 if (fildes >=0 && fildes <= 2)
6261 return 1;
6262 else
6263 return 0;
6264}
6265
6266int
6267getgid ()
6268{
6269 return 100;
6270}
6271
6272int
6273getegid ()
6274{
6275 return 100;
6276}
6277
6278int
6279getuid ()
6280{
6281 return 200;
6282}
6283
6284int
6285geteuid ()
6286{
6287 return 200;
6288}
6289
6290unsigned int
6291sleep (unsigned int seconds)
6292{
6293 unsigned long finalTick;
6294
6295 Delay (seconds * 60UL, &finalTick);
6296 return (0);
6297}
6298#endif /* __MRC__ */
6299
6300#ifdef __MWERKS__
6301#undef getpid
6302int
6303getpid ()
6304{
6305 return 9999;
6306}
6307#endif /* __MWERKS__ */
6308
6309/* Return the path to the directory in which Emacs can create
6310 temporary files. The MacOS "temporary items" directory cannot be
6311 used because it removes the file written by a process when it
6312 exits. In that sense it's more like "/dev/null" than "/tmp" (but
6313 again not exactly). And of course Emacs needs to read back the
6314 files written by its subprocesses. So here we write the files to a
6315 directory "Emacs" in the Preferences Folder. This directory is
6316 created if it does not exist. */
6317static char *
6318GetTempDirName ()
6319{
6320 static char *TempDirName = NULL;
6321 short vRefNum;
6322 long dirID;
6323 OSErr err;
6324 Str255 dirName, fullPath;
6325 CInfoPBRec cpb;
6326 char unixDirName[MAXPATHLEN+1];
6327 DIR *dir;
6328
6329 /* Cache directory name with pointer TempDirName.
6330 Look for it only the first time. */
6331 if (!TempDirName)
6332 {
6333 err = FindFolder (kOnSystemDisk, kPreferencesFolderType,
6334 kCreateFolder, &vRefNum, &dirID);
6335 if (err != noErr)
6336 return NULL;
6337
6338 *fullPath = '\0';
6339 cpb.dirInfo.ioNamePtr = dirName;
6340 cpb.dirInfo.ioDrParID = dirID;
6341
6342 /* Standard ref num to full path name loop */
6343 do {
6344 cpb.dirInfo.ioVRefNum = vRefNum;
6345 cpb.dirInfo.ioFDirIndex = -1;
6346 cpb.dirInfo.ioDrDirID = cpb.dirInfo.ioDrParID;
6347
6348 err = PBGetCatInfo (&cpb, false);
6349
6350 p2cstr (dirName);
6351 strcat (dirName, ":");
6352 if (strlen (fullPath) + strlen (dirName) <= MAXPATHLEN)
6353 {
6354 strcat (dirName, fullPath);
6355 strcpy (fullPath, dirName);
6356 }
6357 else
6358 return NULL;
6359 }
6360 while (cpb.dirInfo.ioDrDirID != fsRtDirID && err == noErr);
6361
6362 if (strlen (fullPath) + 6 <= MAXPATHLEN)
6363 strcat (fullPath, "Emacs:");
6364 else
6365 return NULL;
6366
6367 if (Mac2UnixPathname (fullPath, unixDirName, MAXPATHLEN+1) == 0)
6368 return NULL;
6369
6370 dir = opendir (unixDirName); /* check whether temp directory exists */
6371 if (dir)
6372 closedir (dir);
6373 else if (mkdir (unixDirName, 0700) != 0) /* create it if not */
6374 return NULL;
6375
6376 TempDirName = (char *) malloc (strlen (unixDirName) + 1);
6377 strcpy (TempDirName, unixDirName);
6378 }
6379
6380 return TempDirName;
6381}
6382
6383char *
6384getenv (const char * name)
6385{
6386 if (strcmp (name, "TERM") == 0)
6387 return "vt100";
6388 else if (strcmp (name, "TERMCAP") == 0)
6389 /* for debugging purpose when code was still outputting to dumb terminal */
6390 return "d0|vt100|vt100-am|vt100am|dec vt100:do=[do]:co#100:li#32:cl=[cl]:sf=[sf]:km:\
6391:le=[le]:bs:am:cm=[cm-%d,%d]:nd=[nd]:up=[up]:ce=[ce]:cd=[cd]:so=[so]:se=[se]:\
6392:us=[us]:ue=[ue]:md=[md]:mr=[mr]:mb=[mb]:me=[me]:is=[is]:\
6393:rf=/usr/share/lib/tabset/vt100:rs=[rs]:ks=[ks]:ke=[ke]:\
6394:ku=\\036:kd=\\037:kr=\\035:kl=\\034:kb=[kb]:ho=[ho]:k1=[k1]:k2=[k2]:k3=[k3]:k4=[k4]:\
6395:pt:sr=[sr]:vt#3:xn:sc=[sc]:rc=[rc]:cs=[cs-%d,%d]";
6396 else if (strcmp (name, "TMPDIR") == 0)
6397 return GetTempDirName ();
6398 else
6399 return (NULL);
6400}
6401
6402#ifdef __MRC__
6403/* see Interfaces&Libraries:Interfaces:CIncludes:signal.h */
6404char *sys_siglist[] =
6405{
6406 "Zero is not a signal!!!",
6407 "Abort", /* 1 */
6408 "Interactive user interrupt", /* 2 */ "BAD",
6409 "Floating point exception", /* 4 */ "BAD", "BAD", "BAD",
6410 "Illegal instruction", /* 8 */ "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD",
6411 "Segment violation", /* 16 */ "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD", "BAD",
6412 "Terminal" /* 32 */
6413};
6414#elif __MWERKS__
6415char *sys_siglist[] =
6416{
6417 "Zero is not a signal!!!",
6418 "Abort",
6419 "Floating point exception",
6420 "Illegal instruction",
6421 "Interactive user interrupt",
6422 "Segment violation",
6423 "Terminal"
6424};
6425#else
6426You lose!!!
6427#endif
6428
6429#ifdef __MRC__
6430#include <utsname.h>
6431
6432int
6433uname (struct utsname *name)
6434{
6435 char **systemName;
6436 systemName = GetString (-16413); /* IM - Resource Manager Reference */
6437 if (systemName)
6438 {
6439 BlockMove (*systemName, name->nodename, (*systemName)[0]+1);
6440 p2cstr (name->nodename);
6441 }
6442 else
6443 return -1;
6444}
6445#endif
6446
6447#include <Processes.h>
6448#include <EPPC.h>
6449
6450/* Event class of HLE sent to subprocess. */
6451const OSType kEmacsSubprocessSend = 'ESND';
6452/* Event class of HLE sent back from subprocess. */
6453const OSType kEmacsSubprocessReply = 'ERPY';
6454
6455char *
6456mystrchr (char *s, char c)
6457{
6458 while (*s && *s != c)
6459 {
6460 if (*s == '\\')
6461 s++;
6462 s++;
6463 }
6464
6465 if (*s)
6466 {
6467 *s = '\0';
6468 return s;
6469 }
6470 else
6471 return NULL;
6472}
6473
6474char *
6475mystrtok (char *s)
6476{
6477 while (*s)
6478 s++;
6479
6480 return s + 1;
6481}
6482
6483void
6484mystrcpy (char *to, char *from)
6485{
6486 while (*from)
6487 {
6488 if (*from == '\\')
6489 from++;
6490 *to++ = *from++;
6491 }
6492 *to = '\0';
6493}
6494
6495/* Start a Mac subprocess. Arguments for it is passed in argv (null
6496 terminated). The process should run with the default directory
6497 "workdir", read input from "infn", and write output and error to
6498 "outfn" and "errfn", resp. The Process Manager call
6499 LaunchApplication is used to start the subprocess. We use high
6500 level events as the mechanism to pass arguments to the subprocess
6501 and to make Emacs wait for the subprocess to terminate and pass
6502 back a result code. The bulk of the code here packs the arguments
6503 into one message to be passed together with the high level event.
6504 Emacs also sometimes starts a subprocess using a shell to perform
6505 wildcard filename expansion. Since we don't really have a shell on
6506 the Mac, this case is detected and the starting of the shell is
6507 by-passed. We really need to add code here to do filename
6508 expansion to support such functionality. */
6509int
6510run_mac_command (argv, workdir, infn, outfn, errfn)
6511 unsigned char **argv;
6512 const char *workdir;
6513 const char *infn, *outfn, errfn;
6514{
6515 char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
6516 char macinfn[MAXPATHLEN+1], macoutfn[MAXPATHLEN+1], macerrfn[MAXPATHLEN+1];
6517 int paramlen, argc, newargc, j, retries;
6518 char **newargv, *param, *p;
6519 OSErr iErr;
6520 FSSpec spec;
6521 LaunchParamBlockRec lpbr;
6522 EventRecord sendEvent, replyEvent;
6523 RgnHandle cursorRegionHdl;
6524 TargetID targ;
6525 unsigned long refCon, len;
6526
6527 if (Unix2MacPathname (workdir, macworkdir, MAXPATHLEN+1) == 0)
6528 return -1;
6529 if (Unix2MacPathname (infn, macinfn, MAXPATHLEN+1) == 0)
6530 return -1;
6531 if (Unix2MacPathname (outfn, macoutfn, MAXPATHLEN+1) == 0)
6532 return -1;
6533 if (Unix2MacPathname (errfn, macerrfn, MAXPATHLEN+1) == 0)
6534 return -1;
6535
6536 paramlen = strlen (macworkdir) + strlen (macinfn) + strlen (macoutfn) + strlen (macerrfn) + 4;
6537 /* count nulls at end of strings */
6538
6539 argc = 0;
6540 while (argv[argc])
6541 argc++;
6542
6543 if (argc == 0)
6544 return -1;
6545
6546 /* If a subprocess is invoked with a shell, we receive 3 arguments of the form:
6547 "<path to emacs bins>/sh" "-c" "<path to emacs bins>/<command> <command args>" */
6548 j = strlen (argv[0]);
6549 if (j >= 3 && strcmp (argv[0]+j-3, "/sh") == 0 && argc == 3 && strcmp (argv[1], "-c") == 0)
6550 {
6551 char *command, *t, tempmacpathname[MAXPATHLEN+1];
6552
6553 /* The arguments for the command in argv[2] are separated by spaces. Count them and put
6554 the count in newargc. */
6555 command = (char *) alloca (strlen (argv[2])+2);
6556 strcpy (command, argv[2]);
6557 if (command[strlen (command) - 1] != ' ')
6558 strcat (command, " ");
6559
6560 t = command;
6561 newargc = 0;
6562 t = mystrchr (t, ' ');
6563 while (t)
6564 {
6565 newargc++;
6566 t = mystrchr (t+1, ' ');
6567 }
6568
6569 newargv = (char **) alloca (sizeof (char *) * newargc);
6570
6571 t = command;
6572 for (j = 0; j < newargc; j++)
6573 {
6574 newargv[j] = (char *) alloca (strlen (t) + 1);
6575 mystrcpy (newargv[j], t);
6576
6577 t = mystrtok (t);
6578 paramlen += strlen (newargv[j]) + 1;
6579 }
6580
6581 if (strncmp (newargv[0], "~emacs/", 7) == 0)
6582 {
6583 if (Unix2MacPathname (newargv[0], tempmacpathname, MAXPATHLEN+1) == 0)
6584 return -1;
6585 }
6586 else
6587 { /* sometimes Emacs call "sh" without a path for the command */
6588#if 0
6589 char *t = (char *) alloca (strlen (newargv[0]) + 7 + 1);
6590 strcpy (t, "~emacs/");
6591 strcat (t, newargv[0]);
6592#endif
6593 Lisp_Object path;
6594 openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path, 1);
6595
6596 if (NILP (path))
6597 return -1;
6598 if (Unix2MacPathname (XSTRING (path)->data, tempmacpathname, MAXPATHLEN+1) == 0)
6599 return -1;
6600 }
6601 strcpy (macappname, tempmacpathname);
6602 }
6603 else
6604 {
6605 if (Unix2MacPathname (argv[0], macappname, MAXPATHLEN+1) == 0)
6606 return -1;
6607
6608 newargv = (char **) alloca (sizeof (char *) * argc);
6609 newargc = argc;
6610 for (j = 1; j < argc; j++)
6611 {
6612 if (strncmp (argv[j], "~emacs/", 7) == 0)
6613 {
6614 char *t = strchr (argv[j], ' ');
6615 if (t)
6616 {
6617 char tempcmdname[MAXPATHLEN+1], tempmaccmdname[MAXPATHLEN+1];
6618 strncpy (tempcmdname, argv[j], t-argv[j]);
6619 tempcmdname[t-argv[j]] = '\0';
6620 if (Unix2MacPathname (tempcmdname, tempmaccmdname, MAXPATHLEN+1) == 0)
6621 return -1;
6622 newargv[j] = (char *) alloca (strlen (tempmaccmdname) + strlen (t) + 1);
6623 strcpy (newargv[j], tempmaccmdname);
6624 strcat (newargv[j], t);
6625 }
6626 else
6627 {
6628 char tempmaccmdname[MAXPATHLEN+1];
6629 if (Unix2MacPathname (argv[j], tempmaccmdname, MAXPATHLEN+1) == 0)
6630 return -1;
6631 newargv[j] = (char *) alloca (strlen (tempmaccmdname)+1);
6632 strcpy (newargv[j], tempmaccmdname);
6633 }
6634 }
6635 else
6636 newargv[j] = argv[j];
6637 paramlen += strlen (newargv[j]) + 1;
6638 }
6639 }
6640
6641 /* After expanding all the arguments, we now know the length of the parameter block to be
6642 sent to the subprocess as a message attached to the HLE. */
6643 param = (char *) malloc (paramlen + 1);
6644 if (!param)
6645 return -1;
6646
6647 p = param;
6648 *p++ = newargc; /* first byte of message contains number of arguments for command */
6649 strcpy (p, macworkdir);
6650 p += strlen (macworkdir);
6651 *p++ = '\0'; /* null terminate strings sent so it's possible to use strcpy over there */
6652 strcpy (p, macinfn);
6653 p += strlen (macinfn);
6654 *p++ = '\0';
6655 strcpy (p, macoutfn);
6656 p += strlen (macoutfn);
6657 *p++ = '\0';
6658 strcpy (p, macerrfn);
6659 p += strlen (macerrfn);
6660 *p++ = '\0';
6661 for (j = 1; j < newargc; j++) {
6662 strcpy (p, newargv[j]);
6663 p += strlen (newargv[j]);
6664 *p++ = '\0';
6665 }
6666
6667 c2pstr (macappname);
6668
6669 iErr = FSMakeFSSpec (0, 0, macappname, &spec);
6670
6671 if (iErr != noErr) {
6672 free (param);
6673 return -1;
6674 }
6675
6676 lpbr.launchBlockID = extendedBlock;
6677 lpbr.launchEPBLength = extendedBlockLen;
6678 lpbr.launchControlFlags = launchContinue + launchNoFileFlags;
6679 lpbr.launchAppSpec = &spec;
6680 lpbr.launchAppParameters = NULL;
6681
6682 iErr = LaunchApplication (&lpbr); /* call the subprocess */
6683 if (iErr != noErr) {
6684 free (param);
6685 return -1;
6686 }
6687
6688 sendEvent.what = kHighLevelEvent;
6689 sendEvent.message = kEmacsSubprocessSend; /* Event ID stored in "where" unused */
6690
6691 retries = 3;
6692 do { /* OS may think current subprocess has terminated if previous one terminated recently */
6693 iErr = PostHighLevelEvent (&sendEvent, &lpbr.launchProcessSN, 0, param, paramlen + 1, receiverIDisPSN);
6694 }
6695 while (iErr == sessClosedErr && retries-- > 0);
6696
6697 if (iErr != noErr) {
6698 free (param);
6699 return -1;
6700 }
6701
6702 cursorRegionHdl = NewRgn ();
6703
6704 /* Wait for the subprocess to finish, when it will send us a ERPY high level event */
6705 while (1)
6706 if (WaitNextEvent (highLevelEventMask, &replyEvent, 180, cursorRegionHdl) && replyEvent.message == kEmacsSubprocessReply)
6707 break;
6708
6709 /* The return code is sent through the refCon */
6710 iErr = AcceptHighLevelEvent (&targ, &refCon, NULL, &len);
6711 if (iErr != noErr) {
6712 DisposeHandle ((Handle) cursorRegionHdl);
6713 free (param);
6714 return -1;
6715 }
6716
6717 DisposeHandle ((Handle) cursorRegionHdl);
6718 free (param);
6719
6720 return refCon;
6721}
6722
6723DIR *
6724opendir (const char *dirname)
6725{
6726 char MacPathname[MAXPATHLEN+1];
6727 DIR *dirp;
6728 CInfoPBRec cipb;
6729 int len;
6730
6731 dirp = (DIR *) malloc (sizeof (DIR));
6732 if (!dirp)
6733 return 0;
6734
6735 /* Handle special case when dirname is "/": sets up for readir to
6736 get all mount volumes. */
6737 if (strcmp (dirname, "/") == 0) {
6738 dirp->getting_volumes = 1; /* special all mounted volumes DIR struct */
6739 dirp->current_index = 1; /* index for first volume */
6740 return dirp;
6741 }
6742
6743 /* Handle typical cases: not accessing all mounted volumes. */
6744 if (Unix2MacPathname (dirname, MacPathname, MAXPATHLEN+1) == 0)
6745 return 0;
6746
6747 /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
6748 len = strlen (MacPathname);
6749 if (MacPathname[len - 1] != ':' && len < MAXPATHLEN)
6750 strcat (MacPathname, ":");
6751
6752 c2pstr (MacPathname);
6753 cipb.hFileInfo.ioNamePtr = MacPathname; /* using full pathname so vRefNum and dirID ignored */
6754 cipb.hFileInfo.ioVRefNum = 0;
6755 cipb.hFileInfo.ioDirID = 0;
6756 cipb.hFileInfo.ioFDirIndex = 0; /* set to 0 to get information about specific dir or file */
6757
6758 errno = PBGetCatInfo (&cipb, false);
6759 if (errno != noErr) {
6760 errno = ENOENT;
6761 return 0;
6762 }
6763
6764 if (!(cipb.hFileInfo.ioFlAttrib & 0x10)) /* bit 4 = 1 for directories */
6765 return 0; /* not a directory */
6766
6767 dirp->dir_id = cipb.dirInfo.ioDrDirID; /* used later in readdir */
6768 dirp->getting_volumes = 0;
6769 dirp->current_index = 1; /* index for first file/directory */
6770
6771 return dirp;
6772}
6773
6774int
6775closedir (DIR *dp)
6776{
6777 free (dp);
6778
6779 return 0;
6780}
6781
6782struct dirent *
6783readdir (DIR *dp)
6784{
6785 HParamBlockRec HPBlock;
6786 CInfoPBRec cipb;
6787 static struct dirent s_dirent;
6788 static Str255 s_name;
6789 int done;
6790
6791 /* Handle the root directory containing the mounted volumes. Call
6792 PBHGetVInfo specifying an index to obtain the info for a volume.
6793 PBHGetVInfo returns an error when it receives an index beyond the
6794 last volume, at which time we should return a nil dirent struct
6795 pointer. */
6796 if (dp->getting_volumes) {
6797 HPBlock.volumeParam.ioNamePtr = s_name;
6798 HPBlock.volumeParam.ioVRefNum = 0;
6799 HPBlock.volumeParam.ioVolIndex = dp->current_index;
6800
6801 errno = PBHGetVInfo (&HPBlock, false);
6802 if (errno != noErr) {
6803 errno = ENOENT;
6804 return 0;
6805 }
6806
6807 p2cstr (s_name);
6808 strcat (s_name, "/"); /* need "/" for stat to work correctly */
6809
6810 dp->current_index++;
6811
6812 s_dirent.d_ino = cipb.dirInfo.ioDrDirID;
6813 s_dirent.d_name = s_name;
6814
6815 return &s_dirent;
6816 }
6817 else {
6818 cipb.hFileInfo.ioVRefNum = 0;
6819 cipb.hFileInfo.ioNamePtr = s_name; /* location to receive filename returned */
6820
6821 /* return only visible files */
6822 done = false;
6823 while (!done) {
6824 cipb.hFileInfo.ioDirID = dp->dir_id; /* directory ID found by opendir */
6825 cipb.hFileInfo.ioFDirIndex = dp->current_index;
6826
6827 errno = PBGetCatInfo (&cipb, false);
6828 if (errno != noErr) {
6829 errno = ENOENT;
6830 return 0;
6831 }
6832
6833 /* insist on an visibile entry */
6834 if (cipb.hFileInfo.ioFlAttrib & 0x10) /* directory? */
6835 done = !(cipb.dirInfo.ioDrUsrWds.frFlags & fInvisible);
6836 else
6837 done = !(cipb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible);
6838
6839 dp->current_index++;
6840 }
6841
6842 p2cstr (s_name);
6843
6844 s_dirent.d_ino = cipb.dirInfo.ioDrDirID; /* value unimportant: non-zero for valid file */
6845 s_dirent.d_name = s_name;
6846
6847 return &s_dirent;
6848 }
6849}
6850
6851char *
6852getwd (char *path)
6853{
6854 char MacPathname[MAXPATHLEN+1];
6855 Str255 directoryName;
6856 OSErr errno;
6857 CInfoPBRec cipb;
6858
6859 MacPathname[0] = '\0';
6860 directoryName[0] = '\0';
6861 cipb.dirInfo.ioDrParID = 0;
6862 cipb.dirInfo.ioNamePtr = directoryName; /* empty string = default directory */
6863
6864 do {
6865 cipb.dirInfo.ioVRefNum = 0;
6866 cipb.dirInfo.ioFDirIndex = -1;
6867 cipb.dirInfo.ioDrDirID = cipb.dirInfo.ioDrParID; /* go up to parent each time */
6868
6869 errno = PBGetCatInfo (&cipb, false);
6870 if (errno != noErr) {
6871 errno = ENOENT;
6872 return 0;
6873 }
6874
6875 p2cstr (directoryName);
6876 strcat (directoryName, ":");
6877 strcat (directoryName, MacPathname); /* attach to front since going up directory tree */
6878 strcpy (MacPathname, directoryName);
6879 } while (cipb.dirInfo.ioDrDirID != fsRtDirID); /* until volume's root directory */
6880
6881 if (Mac2UnixPathname (MacPathname, path, MAXPATHLEN+1) == 0)
6882 return 0;
6883 else
6884 return path;
6885}
6886
6887#endif /* macintosh */