diff options
| author | Richard M. Stallman | 1999-09-06 22:32:26 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1999-09-06 22:32:26 +0000 |
| commit | c4ea52a64fc91467e6952d6dc32962b7ca7f940b (patch) | |
| tree | 8d58def20a9e3c79f0af9795809555f49ef86b01 /src | |
| parent | 162100b50740f3d5cbed0d7b8b18cfe098e3c5aa (diff) | |
| download | emacs-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.c | 1634 |
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 | ||
| 39 | You lose!!! | ||
| 40 | #endif | ||
| 41 | #ifndef subprocesses | ||
| 42 | /* Nonzero means delete a process right away if it exits (process.c). */ | ||
| 43 | static int delete_exited_processes; | ||
| 44 | #endif | ||
| 45 | #ifndef HAVE_X_WINDOWS | ||
| 46 | /* Search path for bitmap files (xfns.c). */ | ||
| 47 | Lisp_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 () | |||
| 738 | void | 756 | void |
| 739 | sys_subshell () | 757 | sys_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 | ||
| 859 | static void | 881 | static 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 | ||
| 981 | void | 1003 | void |
| @@ -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\ | ||
| 1297 | nil 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 | ||
| 3490 | int | 3532 | int |
| 3491 | closedir (dirp) | 3533 | closedir (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 | ||
| 5135 | void | 5177 | void |
| 5136 | hft_reset () | 5178 | hft_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 | |||
| 5347 | int | ||
| 5348 | Mac2UnixPathname (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 | |||
| 5398 | extern char *GetTempDirName (); | ||
| 5399 | |||
| 5400 | /* Convert a Unix pathname to Mac form. Approximately reverse of the | ||
| 5401 | above in algorithm. */ | ||
| 5402 | int | ||
| 5403 | Unix2MacPathname (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 | |||
| 5507 | int | ||
| 5508 | stat (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. */ | ||
| 5571 | int | ||
| 5572 | fstat (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 */ | ||
| 5582 | int | ||
| 5583 | mkdir (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 | |||
| 5603 | int | ||
| 5604 | rmdir (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. */ | ||
| 5624 | int | ||
| 5625 | execvp (const char *path, ...) | ||
| 5626 | { | ||
| 5627 | return -1; | ||
| 5628 | } | ||
| 5629 | |||
| 5630 | #endif /* __MRC__ */ | ||
| 5631 | |||
| 5632 | int | ||
| 5633 | utime (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. */ | ||
| 5676 | int | ||
| 5677 | access (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 | ||
| 5718 | int | ||
| 5719 | sys_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 | ||
| 5733 | int | ||
| 5734 | sys_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 | ||
| 5745 | int | ||
| 5746 | sys_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 | ||
| 5757 | int | ||
| 5758 | sys_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 | ||
| 5775 | int | ||
| 5776 | sys_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 | ||
| 5785 | int | ||
| 5786 | sys_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 | ||
| 5803 | extern FILE *fopen (const char *name, const char *mode); | ||
| 5804 | FILE | ||
| 5805 | sys_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 | |||
| 5817 | long 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 | ||
| 5824 | You 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. */ | ||
| 5834 | void | ||
| 5835 | CheckAlarm () | ||
| 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. */ | ||
| 5846 | int | ||
| 5847 | pause () | ||
| 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 | |||
| 5864 | int | ||
| 5865 | alarm (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__ | ||
| 5876 | extern __sigfun signal (int signal, __sigfun signal_func); | ||
| 5877 | __sigfun | ||
| 5878 | sys_signal (int signal_num, __sigfun signal_func) | ||
| 5879 | #elif __MWERKS__ | ||
| 5880 | extern __signal_func_ptr signal (int signal, __signal_func_ptr signal_func); | ||
| 5881 | __signal_func_ptr | ||
| 5882 | sys_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 | ||
| 5908 | extern struct tm *gmtime (const time_t *); | ||
| 5909 | struct tm | ||
| 5910 | sys_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 | ||
| 5918 | extern struct tm *localtime (const time_t *); | ||
| 5919 | struct tm * | ||
| 5920 | sys_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 | ||
| 5928 | extern char *ctime (const time_t *); | ||
| 5929 | char * | ||
| 5930 | sys_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 | ||
| 5938 | extern time_t time (time_t *); | ||
| 5939 | time_t | ||
| 5940 | sys_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 */ | ||
| 5951 | int | ||
| 5952 | wait (int pid) | ||
| 5953 | { | ||
| 5954 | return 0; | ||
| 5955 | } | ||
| 5956 | |||
| 5957 | void | ||
| 5958 | croak (char *badfunc) | ||
| 5959 | { | ||
| 5960 | printf ("%s not yet implemented\r\n", badfunc); | ||
| 5961 | exit (1); | ||
| 5962 | } | ||
| 5963 | |||
| 5964 | char * | ||
| 5965 | index (const char * str, int chr) | ||
| 5966 | { | ||
| 5967 | return strchr (str, chr); | ||
| 5968 | } | ||
| 5969 | |||
| 5970 | char *e[] = { 0 }; | ||
| 5971 | char **environ = &e[0]; | ||
| 5972 | |||
| 5973 | char * | ||
| 5974 | mktemp (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 | |||
| 6001 | static char myPasswdName[PASSWD_FIELD_SIZE]; | ||
| 6002 | static char myPasswdDir[MAXPATHLEN+1]; | ||
| 6003 | |||
| 6004 | static struct passwd myPasswd = | ||
| 6005 | { | ||
| 6006 | myPasswdName, | ||
| 6007 | myPasswdDir, | ||
| 6008 | }; | ||
| 6009 | |||
| 6010 | /* Initialized by main () in macterm.c to pathname of emacs directory. */ | ||
| 6011 | char emacsPasswdDir[MAXPATHLEN+1]; | ||
| 6012 | |||
| 6013 | void | ||
| 6014 | InitEmacsPasswdDir () | ||
| 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 | |||
| 6050 | static struct passwd emacsPasswd = | ||
| 6051 | { | ||
| 6052 | "emacs", | ||
| 6053 | emacsPasswdDir, | ||
| 6054 | }; | ||
| 6055 | |||
| 6056 | static int myPasswdInited = 0; | ||
| 6057 | |||
| 6058 | static void | ||
| 6059 | InitMyPasswd () | ||
| 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 | |||
| 6079 | struct passwd * | ||
| 6080 | getpwuid (uid_t uid) | ||
| 6081 | { | ||
| 6082 | if (!myPasswdInited) | ||
| 6083 | { | ||
| 6084 | InitMyPasswd (); | ||
| 6085 | myPasswdInited = 1; | ||
| 6086 | } | ||
| 6087 | |||
| 6088 | return &myPasswd; | ||
| 6089 | } | ||
| 6090 | |||
| 6091 | struct passwd * | ||
| 6092 | getpwnam (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 | |||
| 6110 | int | ||
| 6111 | fork () | ||
| 6112 | { | ||
| 6113 | return -1; | ||
| 6114 | } | ||
| 6115 | |||
| 6116 | int | ||
| 6117 | kill (int x, int y) | ||
| 6118 | { | ||
| 6119 | return -1; | ||
| 6120 | } | ||
| 6121 | |||
| 6122 | int | ||
| 6123 | sigsetmask (int x) | ||
| 6124 | { | ||
| 6125 | return 0; | ||
| 6126 | } | ||
| 6127 | |||
| 6128 | int | ||
| 6129 | sigblock (int mask) | ||
| 6130 | { | ||
| 6131 | return 0; | ||
| 6132 | } | ||
| 6133 | |||
| 6134 | void | ||
| 6135 | request_sigio (void) | ||
| 6136 | { | ||
| 6137 | } | ||
| 6138 | |||
| 6139 | int | ||
| 6140 | setpgrp () | ||
| 6141 | { | ||
| 6142 | return 0; | ||
| 6143 | } | ||
| 6144 | |||
| 6145 | void | ||
| 6146 | unrequest_sigio (void) | ||
| 6147 | { | ||
| 6148 | } | ||
| 6149 | |||
| 6150 | /* djgpp does not implement pipe either. */ | ||
| 6151 | int | ||
| 6152 | pipe (int _fildes[2]) | ||
| 6153 | { | ||
| 6154 | errno = EACCES; | ||
| 6155 | return -1; | ||
| 6156 | } | ||
| 6157 | |||
| 6158 | /* Hard and symbolic links. */ | ||
| 6159 | int | ||
| 6160 | symlink (const char *name1, const char *name2) | ||
| 6161 | { | ||
| 6162 | errno = ENOENT; | ||
| 6163 | return -1; | ||
| 6164 | } | ||
| 6165 | |||
| 6166 | int | ||
| 6167 | link (const char *name1, const char *name2) | ||
| 6168 | { | ||
| 6169 | errno = ENOENT; | ||
| 6170 | return -1; | ||
| 6171 | } | ||
| 6172 | |||
| 6173 | int | ||
| 6174 | lstat (const char *path, struct stat *sb) | ||
| 6175 | { | ||
| 6176 | return stat (path, sb); | ||
| 6177 | } | ||
| 6178 | |||
| 6179 | int | ||
| 6180 | readlink (const char *path, char *buf, int bufsiz) | ||
| 6181 | { | ||
| 6182 | errno = ENOENT; | ||
| 6183 | return -1; | ||
| 6184 | } | ||
| 6185 | |||
| 6186 | mode_t | ||
| 6187 | umask (mode_t numask) | ||
| 6188 | { | ||
| 6189 | static mode_t mask = 022; | ||
| 6190 | mode_t oldmask = mask; | ||
| 6191 | mask = numask; | ||
| 6192 | return oldmask; | ||
| 6193 | } | ||
| 6194 | |||
| 6195 | int | ||
| 6196 | chmod (const char *path, mode_t mode) | ||
| 6197 | { | ||
| 6198 | /* say it always succeed for now */ | ||
| 6199 | return 0; | ||
| 6200 | } | ||
| 6201 | |||
| 6202 | int | ||
| 6203 | dup (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 | ||
| 6212 | You 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. */ | ||
| 6220 | int | ||
| 6221 | dup2 (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 */ | ||
| 6238 | char * | ||
| 6239 | sbrk (int incr) | ||
| 6240 | { | ||
| 6241 | return (char *) -1; | ||
| 6242 | } | ||
| 6243 | |||
| 6244 | int | ||
| 6245 | fsync (int fd) | ||
| 6246 | { | ||
| 6247 | return 0; | ||
| 6248 | } | ||
| 6249 | |||
| 6250 | int | ||
| 6251 | ioctl (int d, int request, void *argp) | ||
| 6252 | { | ||
| 6253 | return -1; | ||
| 6254 | } | ||
| 6255 | |||
| 6256 | #ifdef __MRC__ | ||
| 6257 | int | ||
| 6258 | isatty (int fildes) | ||
| 6259 | { | ||
| 6260 | if (fildes >=0 && fildes <= 2) | ||
| 6261 | return 1; | ||
| 6262 | else | ||
| 6263 | return 0; | ||
| 6264 | } | ||
| 6265 | |||
| 6266 | int | ||
| 6267 | getgid () | ||
| 6268 | { | ||
| 6269 | return 100; | ||
| 6270 | } | ||
| 6271 | |||
| 6272 | int | ||
| 6273 | getegid () | ||
| 6274 | { | ||
| 6275 | return 100; | ||
| 6276 | } | ||
| 6277 | |||
| 6278 | int | ||
| 6279 | getuid () | ||
| 6280 | { | ||
| 6281 | return 200; | ||
| 6282 | } | ||
| 6283 | |||
| 6284 | int | ||
| 6285 | geteuid () | ||
| 6286 | { | ||
| 6287 | return 200; | ||
| 6288 | } | ||
| 6289 | |||
| 6290 | unsigned int | ||
| 6291 | sleep (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 | ||
| 6302 | int | ||
| 6303 | getpid () | ||
| 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. */ | ||
| 6317 | static char * | ||
| 6318 | GetTempDirName () | ||
| 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 | |||
| 6383 | char * | ||
| 6384 | getenv (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 */ | ||
| 6404 | char *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__ | ||
| 6415 | char *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 | ||
| 6426 | You lose!!! | ||
| 6427 | #endif | ||
| 6428 | |||
| 6429 | #ifdef __MRC__ | ||
| 6430 | #include <utsname.h> | ||
| 6431 | |||
| 6432 | int | ||
| 6433 | uname (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. */ | ||
| 6451 | const OSType kEmacsSubprocessSend = 'ESND'; | ||
| 6452 | /* Event class of HLE sent back from subprocess. */ | ||
| 6453 | const OSType kEmacsSubprocessReply = 'ERPY'; | ||
| 6454 | |||
| 6455 | char * | ||
| 6456 | mystrchr (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 | |||
| 6474 | char * | ||
| 6475 | mystrtok (char *s) | ||
| 6476 | { | ||
| 6477 | while (*s) | ||
| 6478 | s++; | ||
| 6479 | |||
| 6480 | return s + 1; | ||
| 6481 | } | ||
| 6482 | |||
| 6483 | void | ||
| 6484 | mystrcpy (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. */ | ||
| 6509 | int | ||
| 6510 | run_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 | |||
| 6723 | DIR * | ||
| 6724 | opendir (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 | |||
| 6774 | int | ||
| 6775 | closedir (DIR *dp) | ||
| 6776 | { | ||
| 6777 | free (dp); | ||
| 6778 | |||
| 6779 | return 0; | ||
| 6780 | } | ||
| 6781 | |||
| 6782 | struct dirent * | ||
| 6783 | readdir (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 | |||
| 6851 | char * | ||
| 6852 | getwd (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 */ | ||