comparison src/sysdep.c @ 209:41ff10fd062f r20-4b3

Import from CVS: tag r20-4b3
author cvs
date Mon, 13 Aug 2007 10:04:58 +0200
parents 850242ba4a81
children 78478c60bfcd
comparison
equal deleted inserted replaced
208:f427b8ec4379 209:41ff10fd062f
75 #define _P_WAIT 0 75 #define _P_WAIT 0
76 int _CRTAPI1 _spawnlp (int, const char *, const char *, ...); 76 int _CRTAPI1 _spawnlp (int, const char *, const char *, ...);
77 int _CRTAPI1 _getpid (void); 77 int _CRTAPI1 _getpid (void);
78 #endif 78 #endif
79 79
80 /* ------------------------------- */
81 /* VMS includes */
82 /* ------------------------------- */
83
84 #ifdef VMS
85 #include <ttdef.h>
86 #include <tt2def.h>
87 #include <iodef.h>
88 #include <ssdef.h>
89 #include <descrip.h>
90 #include <fibdef.h>
91 #include <atrdef.h>
92 #undef F_SETFL
93 #ifndef RAB/*$C_BID -- suppress compiler warnings */
94 #include <rab.h>
95 #endif
96 #define MAXIOSIZE (32 * PAGESIZE) /* Don't I/O more than 32 blocks at a time */
97 #endif /* VMS */
98 80
99 /* ------------------------------- */ 81 /* ------------------------------- */
100 /* TTY definitions */ 82 /* TTY definitions */
101 /* ------------------------------- */ 83 /* ------------------------------- */
102 84
252 Since hardly any systems don't have subprocess support, 234 Since hardly any systems don't have subprocess support,
253 however, there doesn't seem to be much point. */ 235 however, there doesn't seem to be much point. */
254 if (wait (0) == pid) 236 if (wait (0) == pid)
255 return; 237 return;
256 } 238 }
257 #elif defined (VMS)
258 int status = SYS$FORCEX (&pid, 0, 0);
259 return;
260
261 #elif defined (HAVE_WAITPID) 239 #elif defined (HAVE_WAITPID)
262 /* Note that, whenever any subprocess terminates (asynch. or synch.), 240 /* Note that, whenever any subprocess terminates (asynch. or synch.),
263 the SIGCHLD handler will be called and it will call wait(). Thus 241 the SIGCHLD handler will be called and it will call wait(). Thus
264 we cannot just call wait() ourselves, and we can't block SIGCHLD 242 we cannot just call wait() ourselves, and we can't block SIGCHLD
265 and then call wait(), because then if an asynch. process dies 243 and then call wait(), because then if an asynch. process dies
419 and nonzero means something different. */ 397 and nonzero means something different. */
420 ioctl (channel, TIOCFLUSH, &zero); 398 ioctl (channel, TIOCFLUSH, &zero);
421 #endif 399 #endif
422 } 400 }
423 401
424 #ifndef VMS
425 #ifndef MSDOS 402 #ifndef MSDOS
426 #ifndef WINDOWSNT 403 #ifndef WINDOWSNT
427 /* Set up the terminal at the other end of a pseudo-terminal that 404 /* Set up the terminal at the other end of a pseudo-terminal that
428 we will be controlling an inferior through. 405 we will be controlling an inferior through.
429 It should not echo or do line-editing, since that is done 406 It should not echo or do line-editing, since that is done
531 } 508 }
532 #endif /* RTU */ 509 #endif /* RTU */
533 } 510 }
534 #endif /* WINDOWSNT */ 511 #endif /* WINDOWSNT */
535 #endif /* not MSDOS */ 512 #endif /* not MSDOS */
536 #endif /* not VMS */
537 513
538 #endif /* not NO_SUBPROCESSES */ 514 #endif /* not NO_SUBPROCESSES */
539 515
540 516
541 #if !defined (VMS) && !defined (SIGTSTP) && !defined (USG_JOBCTRL) 517 #if !defined (SIGTSTP) && !defined (USG_JOBCTRL)
542 518
543 /* Record a signal code and the handler for it. */ 519 /* Record a signal code and the handler for it. */
544 struct save_signal 520 struct save_signal
545 { 521 {
546 int code; 522 int code;
684 wait_for_termination (pid); 660 wait_for_termination (pid);
685 #endif 661 #endif
686 restore_signal_handlers (saved_handlers); 662 restore_signal_handlers (saved_handlers);
687 } 663 }
688 664
689 #endif /* !defined (VMS) && !defined (SIGTSTP) && !defined (USG_JOBCTRL) */ 665 #endif /* !defined (SIGTSTP) && !defined (USG_JOBCTRL) */
690 666
691 667
692 668
693 /* Suspend the Emacs process; give terminal to its superior. */ 669 /* Suspend the Emacs process; give terminal to its superior. */
694 void 670 void
695 sys_suspend (void) 671 sys_suspend (void)
696 { 672 {
697 #ifdef VMS 673 #if defined (SIGTSTP) && !defined (MSDOS)
698 /* "Foster" parentage allows emacs to return to a subprocess that attached
699 to the current emacs as a cheaper than starting a whole new process. This
700 is set up by KEPTEDITOR.COM. */
701 unsigned long parent_id, foster_parent_id;
702 char *fpid_string;
703
704 fpid_string = getenv ("EMACS_PARENT_PID");
705 if (fpid_string != NULL)
706 {
707 sscanf (fpid_string, "%x", &foster_parent_id);
708 if (foster_parent_id != 0)
709 parent_id = foster_parent_id;
710 else
711 parent_id = getppid ();
712 }
713 else
714 parent_id = getppid ();
715
716 xfree (fpid_string); /* On VMS, this was malloc'd */
717
718 if (parent_id && parent_id != 0xffffffff)
719 {
720 SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
721 int status = LIB$ATTACH (&parent_id) & 1;
722 signal (SIGINT, oldsig);
723 return status;
724 }
725 else
726 {
727 struct {
728 int l;
729 char *a;
730 } d_prompt;
731 d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */
732 d_prompt.a = "Emacs: "; /* Just a reminder */
733 LIB$SPAWN (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
734 return 1;
735 }
736 return -1;
737 #elif defined (SIGTSTP) && !defined (MSDOS)
738 { 674 {
739 int pgrp = EMACS_GET_PROCESS_GROUP (); 675 int pgrp = EMACS_GET_PROCESS_GROUP ();
740 EMACS_KILLPG (pgrp, SIGTSTP); 676 EMACS_KILLPG (pgrp, SIGTSTP);
741 } 677 }
742 678
886 822
887 #ifdef HAVE_TTY 823 #ifdef HAVE_TTY
888 assert (DEVICE_TTY_P (d)); 824 assert (DEVICE_TTY_P (d));
889 { 825 {
890 int input_fd = CONSOLE_TTY_DATA (con)->infd; 826 int input_fd = CONSOLE_TTY_DATA (con)->infd;
891 #ifdef MSDOS 827 #if defined (MSDOS) || defined(WIN32)
892 DEVICE_TTY_DATA (d)->ospeed = 15; 828 DEVICE_TTY_DATA (d)->ospeed = 15;
893 #elif defined (VMS)
894 struct vms_sensemode sg;
895
896 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
897 &sg.class, 12, 0, 0, 0, 0 );
898 DEVICE_TTY_DATA (d)->ospeed = sg.xmit_baud;
899 #elif defined (HAVE_TERMIOS) 829 #elif defined (HAVE_TERMIOS)
900 struct termios sg; 830 struct termios sg;
901 831
902 sg.c_cflag = B9600; 832 sg.c_cflag = B9600;
903 tcgetattr (input_fd, &sg); 833 tcgetattr (input_fd, &sg);
915 tcgetattr (input_fd, &sg); 845 tcgetattr (input_fd, &sg);
916 # else 846 # else
917 ioctl (input_fd, TCGETA, &sg); 847 ioctl (input_fd, TCGETA, &sg);
918 # endif 848 # endif
919 DEVICE_TTY_DATA (d)->ospeed = sg.c_cflag & CBAUD; 849 DEVICE_TTY_DATA (d)->ospeed = sg.c_cflag & CBAUD;
920 #else /* neither VMS nor TERMIOS nor TERMIO */ 850 #else /* neither TERMIOS nor TERMIO */
921 struct sgttyb sg; 851 struct sgttyb sg;
922 852
923 sg.sg_ospeed = B9600; 853 sg.sg_ospeed = B9600;
924 if (ioctl (input_fd, TIOCGETP, &sg) < 0) 854 if (ioctl (input_fd, TIOCGETP, &sg) < 0)
925 abort (); 855 abort ();
1347 #ifdef HAVE_TCATTR 1277 #ifdef HAVE_TCATTR
1348 /* We have those nifty POSIX tcmumbleattr functions. */ 1278 /* We have those nifty POSIX tcmumbleattr functions. */
1349 if (tcgetattr (fd, &settings->main) < 0) 1279 if (tcgetattr (fd, &settings->main) < 0)
1350 return -1; 1280 return -1;
1351 1281
1352 #else 1282 #elif defined HAVE_TERMIO
1353 #ifdef HAVE_TERMIO
1354 /* The SYSV-style interface? */ 1283 /* The SYSV-style interface? */
1355 if (ioctl (fd, TCGETA, &settings->main) < 0) 1284 if (ioctl (fd, TCGETA, &settings->main) < 0)
1356 return -1; 1285 return -1;
1357 1286
1358 #else 1287 #elif !defined MSDOS && !defined(WIN32)
1359 #ifdef VMS
1360 /* Vehemently Monstrous System? :-) */
1361 if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
1362 &settings->main.class, 12, 0, 0, 0, 0)
1363 & 1))
1364 return -1;
1365
1366 #else
1367 #ifndef MSDOS
1368 /* I give up - I hope you have the BSD ioctls. */ 1288 /* I give up - I hope you have the BSD ioctls. */
1369 if (ioctl (fd, TIOCGETP, &settings->main) < 0) 1289 if (ioctl (fd, TIOCGETP, &settings->main) < 0)
1370 return -1; 1290 return -1;
1371 #endif /* not MSDOS */
1372 #endif /* not VMS */
1373 #endif /* HAVE_TERMIO */
1374 #endif /* HAVE_TCATTR */ 1291 #endif /* HAVE_TCATTR */
1375 1292
1376 /* Suivant - Do we have to get struct ltchars data? */ 1293 /* Suivant - Do we have to get struct ltchars data? */
1377 #ifdef HAVE_LTCHARS 1294 #ifdef HAVE_LTCHARS
1378 if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0) 1295 if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
1433 && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0) 1350 && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0)
1434 break; 1351 break;
1435 else 1352 else
1436 continue; 1353 continue;
1437 } 1354 }
1438 #else 1355 #elif defined HAVE_TERMIO
1439 #ifdef HAVE_TERMIO
1440 /* The SYSV-style interface? */ 1356 /* The SYSV-style interface? */
1441 if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0) 1357 if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
1442 return -1; 1358 return -1;
1443 1359
1444 #else 1360 #elif !defined(MSDOS) && !defined(WIN32)
1445 #ifdef VMS
1446 /* Vehemently Monstrous System? :-) */
1447 if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
1448 &settings->main.class, 12, 0, 0, 0, 0)
1449 & 1))
1450 return -1;
1451
1452 #else
1453 #ifndef MSDOS
1454 /* I give up - I hope you have the BSD ioctls. */ 1361 /* I give up - I hope you have the BSD ioctls. */
1455 if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0) 1362 if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
1456 return -1; 1363 return -1;
1457 #endif /* not MSDOS */
1458 #endif /* VMS */
1459 #endif /* HAVE_TERMIO */
1460 #endif /* HAVE_TCATTR */ 1364 #endif /* HAVE_TCATTR */
1461 1365
1462 /* Suivant - Do we have to get struct ltchars data? */ 1366 /* Suivant - Do we have to get struct ltchars data? */
1463 #ifdef HAVE_LTCHARS 1367 #ifdef HAVE_LTCHARS
1464 if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0) 1368 if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
1634 or via TELNET or the like, but does no harm elsewhere. */ 1538 or via TELNET or the like, but does no harm elsewhere. */
1635 tty.main.c_iflag &= ~IGNBRK; 1539 tty.main.c_iflag &= ~IGNBRK;
1636 tty.main.c_iflag &= ~BRKINT; 1540 tty.main.c_iflag &= ~BRKINT;
1637 #endif /* AIX */ 1541 #endif /* AIX */
1638 #else /* if not HAVE_TERMIO */ 1542 #else /* if not HAVE_TERMIO */
1639 #ifndef MSDOS 1543 #if !defined(MSDOS) && !defined(WIN32)
1640 con->tty_erase_char = make_char (tty.main.sg_erase); 1544 con->tty_erase_char = make_char (tty.main.sg_erase);
1641 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS); 1545 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1642 if (TTY_FLAGS (con).meta_key) 1546 if (TTY_FLAGS (con).meta_key)
1643 tty.main.sg_flags |= ANYP; 1547 tty.main.sg_flags |= ANYP;
1644 /* #### should we be using RAW mode here? */ 1548 /* #### should we be using RAW mode here? */
1645 tty.main.sg_flags |= /* interrupt_input ? RAW : */ CBREAK; 1549 tty.main.sg_flags |= /* interrupt_input ? RAW : */ CBREAK;
1646 #endif /* not MSDOS */ 1550 #endif /* not MSDOS or WIN32 */
1647 #endif /* not HAVE_TERMIO */ 1551 #endif /* not HAVE_TERMIO */
1648 1552
1649 /* If going to use CBREAK mode, we must request C-g to interrupt 1553 /* If going to use CBREAK mode, we must request C-g to interrupt
1650 and turn off start and stop chars, etc. If not going to use 1554 and turn off start and stop chars, etc. If not going to use
1651 CBREAK mode, do this anyway so as to turn off local flow 1555 CBREAK mode, do this anyway so as to turn off local flow
1718 write (output_fd, "\033[20l", 5); 1622 write (output_fd, "\033[20l", 5);
1719 } 1623 }
1720 #endif 1624 #endif
1721 #endif 1625 #endif
1722 1626
1723 #ifdef VMS
1724 /* Appears to do nothing when in PASTHRU mode.
1725 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
1726 interrupt_signal, oob_chars, 0, 0, 0, 0);
1727 */
1728 queue_kbd_input (0);
1729 #endif /* VMS */
1730
1731 #if 0 /* We do our own buffering with lstreams. */ 1627 #if 0 /* We do our own buffering with lstreams. */
1732 #ifdef _IOFBF 1628 #ifdef _IOFBF
1733 /* This symbol is defined on recent USG systems. 1629 /* This symbol is defined on recent USG systems.
1734 Someone says without this call USG won't really buffer the file 1630 Someone says without this call USG won't really buffer the file
1735 even with a call to setbuf. */ 1631 even with a call to setbuf. */
1832 { 1728 {
1833 *widthp = size.ws_col; 1729 *widthp = size.ws_col;
1834 *heightp = size.ws_row; 1730 *heightp = size.ws_row;
1835 } 1731 }
1836 } 1732 }
1837 #else 1733 #elif defined TIOCGSIZE
1838 #ifdef TIOCGSIZE
1839 { 1734 {
1840 /* SunOS - style. */ 1735 /* SunOS - style. */
1841 struct ttysize size; 1736 struct ttysize size;
1842 1737
1843 if (ioctl (input_fd, TIOCGSIZE, &size) == -1) 1738 if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1846 { 1741 {
1847 *widthp = size.ts_cols; 1742 *widthp = size.ts_cols;
1848 *heightp = size.ts_lines; 1743 *heightp = size.ts_lines;
1849 } 1744 }
1850 } 1745 }
1851 #else 1746 #elif defined MSDOS
1852 #ifdef VMS
1853 {
1854 struct vms_sensemode tty;
1855
1856 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
1857 &tty.class, 12, 0, 0, 0, 0);
1858 *widthp = tty.scr_wid;
1859 *heightp = tty.scr_len;
1860 }
1861 #else
1862 #ifdef MSDOS
1863
1864 *widthp = FrameCols (); 1747 *widthp = FrameCols ();
1865 *heightp = FrameRows (); 1748 *heightp = FrameRows ();
1866 1749
1867 #else /* system doesn't know size */ 1750 #else /* system doesn't know size */
1868 1751
1869 *widthp = 0; 1752 *widthp = 0;
1870 *heightp = 0; 1753 *heightp = 0;
1871 1754
1872 #endif /* not MSDOS */ 1755 #endif /* not !TIOCGWINSZ */
1873 #endif /* not VMS */
1874 #endif /* not SunOS-style */
1875 #endif /* not BSD-style */
1876 } 1756 }
1877 1757
1878 #endif /* HAVE_TTY */ 1758 #endif /* HAVE_TTY */
1879 1759
1880 1760
1961 1841
1962 #ifdef AIXHFT 1842 #ifdef AIXHFT
1963 hft_reset (con); 1843 hft_reset (con);
1964 #endif 1844 #endif
1965 1845
1966 #ifdef VMS
1967 stop_vms_input (con);
1968 #endif
1969 } 1846 }
1970 1847
1971 #endif /* HAVE_TTY */ 1848 #endif /* HAVE_TTY */
1972 1849
1973 void 1850 void
2139 } 2016 }
2140 2017
2141 #endif /* AIXHFT */ 2018 #endif /* AIXHFT */
2142 2019
2143 2020
2144 /* ------------------------------------------------------ */
2145 /* TTY stuff under VMS */
2146 /* ------------------------------------------------------ */
2147
2148 /***** #### this is all broken ****/
2149
2150 #ifdef VMS
2151
2152 /* Assigning an input channel is done at the start of Emacs execution.
2153 This is called each time Emacs is resumed, also, but does nothing
2154 because input_chain is no longer zero. */
2155
2156 void
2157 init_vms_input (void)
2158 {
2159 /* #### broken. */
2160 int status;
2161
2162 if (input_fd == 0)
2163 {
2164 status = SYS$ASSIGN (&vms_input_dsc, &input_fd, 0, 0);
2165 if (! (status & 1))
2166 LIB$STOP (status);
2167 }
2168 }
2169
2170 /* Deassigning the input channel is done before exiting. */
2171
2172 static void
2173 stop_vms_input (struct console *con)
2174 {
2175 int input_fd = CONSOLE_TTY_DATA (con)->infd;
2176 return SYS$DASSGN (input_fd);
2177 }
2178
2179 static short vms_input_buffer;
2180
2181 /* Request reading one character into the keyboard buffer.
2182 This is done as soon as the buffer becomes empty. */
2183
2184 static void
2185 queue_vms_kbd_input (struct console *con)
2186 {
2187 int input_fd = CONSOLE_TTY_DATA (con)->infd;
2188 int status;
2189 vms_waiting_for_ast = 0;
2190 vms_stop_input = 0;
2191 status = SYS$QIO (0, input_fd, IO$_READVBLK,
2192 &vms_input_iosb, vms_kbd_input_ast, 1,
2193 &vms_input_buffer, 1, 0, vms_terminator_mask, 0, 0);
2194 }
2195
2196 static int vms_input_count;
2197
2198 /* Ast routine that is called when keyboard input comes in
2199 in accord with the SYS$QIO above. */
2200
2201 static void
2202 vms_kbd_input_ast (struct console *con)
2203 {
2204 int c = -1;
2205 int old_errno = errno;
2206 extern EMACS_TIME *input_available_clear_time;
2207
2208 if (vms_waiting_for_ast)
2209 SYS$SETEF (vms_input_ef);
2210 vms_waiting_for_ast = 0;
2211 vms_input_count++;
2212 #ifdef ASTDEBUG
2213 if (vms_input_count == 25)
2214 exit (1);
2215 printf ("Ast # %d,", vms_input_count);
2216 printf (" iosb = %x, %x, %x, %x",
2217 vms_input_iosb.offset, vms_input_iosb.status,
2218 vms_input_iosb.termlen, vms_input_iosb.term);
2219 #endif
2220 if (vms_input_iosb.offset)
2221 {
2222 c = vms_input_buffer;
2223 #ifdef ASTDEBUG
2224 printf (", char = 0%o", c);
2225 #endif
2226 }
2227 #ifdef ASTDEBUG
2228 printf ("\n");
2229 fflush (stdout);
2230 emacs_sleep (1);
2231 #endif
2232 if (! vms_stop_input)
2233 queue_vms_kbd_input (con);
2234 if (c >= 0)
2235 kbd_buffer_store_char (c);
2236
2237 if (input_available_clear_time)
2238 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
2239 errno = old_errno;
2240 }
2241
2242 #if 0 /* Unused */
2243 /* Wait until there is something in kbd_buffer. */
2244
2245 void
2246 vms_wait_for_kbd_input (void)
2247 {
2248 /* This function can GC */
2249 extern int have_process_input, process_exited;
2250
2251 /* If already something, avoid doing system calls. */
2252 if (detect_input_pending (0))
2253 {
2254 return;
2255 }
2256 /* Clear a flag, and tell ast routine above to set it. */
2257 SYS$CLREF (vms_input_ef);
2258 vms_waiting_for_ast = 1;
2259 /* Check for timing error: ast happened while we were doing that. */
2260 if (!detect_input_pending (0))
2261 {
2262 /* No timing error: wait for flag to be set. */
2263 set_waiting_for_input (0);
2264 SYS$WFLOR (vms_input_ef, vms_input_eflist);
2265 clear_waiting_for_input (0);
2266 if (!detect_input_pending (0))
2267 /* Check for subprocess input availability */
2268 {
2269 int dsp = have_process_input || process_exited;
2270
2271 SYS$CLREF (vms_process_ef);
2272 if (have_process_input)
2273 process_command_input ();
2274 if (process_exited)
2275 process_exit ();
2276 if (dsp)
2277 {
2278 MARK_MODELINE_CHANGED;
2279 redisplay ();
2280 }
2281 }
2282 }
2283 vms_waiting_for_ast = 0;
2284 }
2285 #endif
2286
2287 /* Get rid of any pending QIO, when we are about to suspend
2288 or when we want to throw away pending input.
2289 We wait for a positive sign that the AST routine has run
2290 and therefore there is no I/O request queued when we return.
2291 SYS$SETAST is used to avoid a timing error. */
2292
2293 static void
2294 vms_end_kbd_input (struct console *con)
2295 {
2296 int input_fd;
2297
2298 assert (CONSOLE_TTY_P (con));
2299 input_fd = CONSOLE_TTY_DATA (con)->infd;
2300 #ifdef ASTDEBUG
2301 printf ("At end_kbd_input.\n");
2302 fflush (stdout);
2303 emacs_sleep (1);
2304 #endif
2305 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_char! */
2306 {
2307 SYS$CANCEL (input_fd);
2308 return;
2309 }
2310
2311 SYS$SETAST (0);
2312 /* Clear a flag, and tell ast routine above to set it. */
2313 SYS$CLREF (vms_input_ef);
2314 vms_waiting_for_ast = 1;
2315 vms_stop_input = 1;
2316 SYS$CANCEL (input_fd);
2317 SYS$SETAST (1);
2318 SYS$WAITFR (vms_input_ef);
2319 vms_waiting_for_ast = 0;
2320 }
2321
2322 #if 0 /* Unused */
2323 /* Wait for either input available or time interval expiry. */
2324
2325 void
2326 vms_input_wait_timeout (int timeval) /* Time to wait, in seconds */
2327 {
2328 int time [2];
2329 static int zero = 0;
2330 static int large = -10000000;
2331
2332 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
2333
2334 /* If already something, avoid doing system calls. */
2335 if (detect_input_pending (0))
2336 {
2337 return;
2338 }
2339 /* Clear a flag, and tell ast routine above to set it. */
2340 SYS$CLREF (vms_input_ef);
2341 vms_waiting_for_ast = 1;
2342 /* Check for timing error: ast happened while we were doing that. */
2343 if (!detect_input_pending (0))
2344 {
2345 /* No timing error: wait for flag to be set. */
2346 SYS$CANTIM (1, 0);
2347 if (SYS$SETIMR (vms_timer_ef, time, 0, 1) & 1) /* Set timer */
2348 SYS$WFLOR (vms_timer_ef, vms_timer_eflist); /* Wait for timer expiry or input */
2349 }
2350 vms_waiting_for_ast = 0;
2351 }
2352 #endif /* 0 */
2353
2354 #endif /* VMS */
2355
2356
2357 /************************************************************************/ 2021 /************************************************************************/
2358 /* limits of text/data segments */ 2022 /* limits of text/data segments */
2359 /************************************************************************/ 2023 /************************************************************************/
2360 2024
2361 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */ 2025 /* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
2497 /* init_system_name sets up the string for the Lisp function 2161 /* init_system_name sets up the string for the Lisp function
2498 system-name to return. */ 2162 system-name to return. */
2499 2163
2500 extern Lisp_Object Vsystem_name; 2164 extern Lisp_Object Vsystem_name;
2501 2165
2502 #if defined (HAVE_SOCKETS) && !defined (VMS) 2166 #ifdef HAVE_SOCKETS
2503 # include <sys/socket.h> 2167 # include <sys/socket.h>
2504 # include <netdb.h> 2168 # include <netdb.h>
2505 #endif /* HAVE_SOCKETS and not VMS */ 2169 #endif /* HAVE_SOCKETS */
2506 2170
2507 void 2171 void
2508 init_system_name (void) 2172 init_system_name (void)
2509 { 2173 {
2510 #if defined (VMS) 2174 #ifndef HAVE_GETHOSTNAME
2511 char *sp, *end;
2512 if ((sp = egetenv ("SYS$NODE")) == 0)
2513 Vsystem_name = build_string ("vax-vms");
2514 else if ((end = strchr (sp, ':')) == 0)
2515 Vsystem_name = build_string (sp);
2516 else
2517 Vsystem_name = make_string ((Bufbyte *) sp, end - sp);
2518 #elif !defined (HAVE_GETHOSTNAME)
2519 struct utsname uts; 2175 struct utsname uts;
2520 uname (&uts); 2176 uname (&uts);
2521 Vsystem_name = build_string (uts.nodename); 2177 Vsystem_name = build_string (uts.nodename);
2522 #else /* HAVE_GETHOSTNAME */ 2178 #else /* HAVE_GETHOSTNAME */
2523 unsigned int hostname_size = 256; 2179 unsigned int hostname_size = 256;
2582 strcpy (hostname, fqdn); 2238 strcpy (hostname, fqdn);
2583 } 2239 }
2584 } 2240 }
2585 # endif /* HAVE_SOCKETS */ 2241 # endif /* HAVE_SOCKETS */
2586 Vsystem_name = build_string (hostname); 2242 Vsystem_name = build_string (hostname);
2587 #endif /* HAVE_GETHOSTNAME and not VMS */ 2243 #endif /* HAVE_GETHOSTNAME */
2588 { 2244 {
2589 Bufbyte *p; 2245 Bufbyte *p;
2590 Bytecount i; 2246 Bytecount i;
2591 2247
2592 for (i = 0, p = XSTRING_DATA (Vsystem_name); 2248 for (i = 0, p = XSTRING_DATA (Vsystem_name);
2602 2258
2603 /************************************************************************/ 2259 /************************************************************************/
2604 /* Emulation of select() */ 2260 /* Emulation of select() */
2605 /************************************************************************/ 2261 /************************************************************************/
2606 2262
2607 #ifndef VMS
2608 #ifndef HAVE_SELECT 2263 #ifndef HAVE_SELECT
2609 2264
2610 ERROR: XEmacs requires a working select(). 2265 ERROR: XEmacs requires a working select().
2611 2266
2612 #endif /* not HAVE_SELECT */ 2267 #endif /* not HAVE_SELECT */
2613 #endif /* not VMS */
2614 2268
2615 2269
2616 /************************************************************************/ 2270 /************************************************************************/
2617 /* Emulation of signal stuff */ 2271 /* Emulation of signal stuff */
2618 /************************************************************************/ 2272 /************************************************************************/
2706 /* Emulation of strerror() */ 2360 /* Emulation of strerror() */
2707 /************************************************************************/ 2361 /************************************************************************/
2708 2362
2709 #ifndef HAVE_STRERROR 2363 #ifndef HAVE_STRERROR
2710 2364
2711 #if defined (VMS) && defined (LINK_CRTL_SHARE) && defined (SHAREABLE_LIB_BUG)
2712
2713 /* Variables declared noshare and initialized in sharable libraries
2714 cannot be shared. The VMS linker incorrectly forces you to use a private
2715 version which is uninitialized... If not for this "feature", we
2716 could use the C library definition of sys_nerr and sys_errlist. */
2717 CONST char *sys_errlist[] =
2718 {
2719 "error 0",
2720 "not owner",
2721 "no such file or directory",
2722 "no such process",
2723 "interrupted system call",
2724 "I/O error",
2725 "no such device or address",
2726 "argument list too long",
2727 "exec format error",
2728 "bad file number",
2729 "no child process",
2730 "no more processes",
2731 "not enough memory",
2732 "permission denied",
2733 "bad address",
2734 "block device required",
2735 "mount devices busy",
2736 "file exists",
2737 "cross-device link",
2738 "no such device",
2739 "not a directory",
2740 "is a directory",
2741 "invalid argument",
2742 "file table overflow",
2743 "too many open files",
2744 "not a typewriter",
2745 "text file busy",
2746 "file too big",
2747 "no space left on device",
2748 "illegal seek",
2749 "read-only file system",
2750 "too many links",
2751 "broken pipe",
2752 "math argument",
2753 "result too large",
2754 "I/O stream empty",
2755 "vax/vms specific error code nontranslatable error"
2756 };
2757 int sys_nerr = countof (sys_errlist);
2758
2759 #endif /* VMS & LINK_CRTL_SHARE & SHAREABLE_LIB_BUG */
2760
2761
2762 #if !defined(NeXT) && !defined(__alpha) && !defined(MACH) && !defined(LINUX) && !defined(IRIX) && !defined(__NetBSD__) 2365 #if !defined(NeXT) && !defined(__alpha) && !defined(MACH) && !defined(LINUX) && !defined(IRIX) && !defined(__NetBSD__)
2763 /* Linux added here by Raymond L. Toy <toy@alydar.crd.ge.com> for XEmacs. */ 2366 /* Linux added here by Raymond L. Toy <toy@alydar.crd.ge.com> for XEmacs. */
2764 /* Irix added here by gparker@sni-usa.com for XEmacs. */ 2367 /* Irix added here by gparker@sni-usa.com for XEmacs. */
2765 /* NetBSD added here by James R Grinter <jrg@doc.ic.ac.uk> for XEmacs */ 2368 /* NetBSD added here by James R Grinter <jrg@doc.ic.ac.uk> for XEmacs */
2766 extern CONST char *sys_errlist[]; 2369 extern CONST char *sys_errlist[];
2790 /************************************************************************/ 2393 /************************************************************************/
2791 2394
2792 #define PATHNAME_CONVERT_OUT(path) \ 2395 #define PATHNAME_CONVERT_OUT(path) \
2793 GET_C_CHARPTR_EXT_FILENAME_DATA_ALLOCA (path, path) 2396 GET_C_CHARPTR_EXT_FILENAME_DATA_ALLOCA (path, path)
2794 2397
2795 /***** VMS versions are at the bottom of this file *****/
2796 /***** MSDOS versions are in msdos.c *****/ 2398 /***** MSDOS versions are in msdos.c *****/
2797 2399
2798 /***************** low-level calls ****************/ 2400 /***************** low-level calls ****************/
2799 2401
2800 /* 2402 /*
2867 #endif /* ENCAPSULATE_CLOSE */ 2469 #endif /* ENCAPSULATE_CLOSE */
2868 2470
2869 int 2471 int
2870 sys_read_1 (int fildes, void *buf, unsigned int nbyte, int allow_quit) 2472 sys_read_1 (int fildes, void *buf, unsigned int nbyte, int allow_quit)
2871 { 2473 {
2872 #ifdef VMS
2873 return vms_read (fildes, buf, nbyte);
2874 #else
2875 int rtnval; 2474 int rtnval;
2876 2475
2877 /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */ 2476 /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2878 while ((rtnval = read (fildes, buf, nbyte)) == -1 2477 while ((rtnval = read (fildes, buf, nbyte)) == -1
2879 && (errno == EINTR)) 2478 && (errno == EINTR))
2880 { 2479 {
2881 if (allow_quit) 2480 if (allow_quit)
2882 REALLY_QUIT; 2481 REALLY_QUIT;
2883 } 2482 }
2884 return rtnval; 2483 return rtnval;
2885 #endif
2886 } 2484 }
2887 2485
2888 #ifdef ENCAPSULATE_READ 2486 #ifdef ENCAPSULATE_READ
2889 int 2487 int
2890 sys_read (int fildes, void *buf, unsigned int nbyte) 2488 sys_read (int fildes, void *buf, unsigned int nbyte)
2894 #endif /* ENCAPSULATE_READ */ 2492 #endif /* ENCAPSULATE_READ */
2895 2493
2896 int 2494 int
2897 sys_write_1 (int fildes, CONST void *buf, unsigned int nbyte, int allow_quit) 2495 sys_write_1 (int fildes, CONST void *buf, unsigned int nbyte, int allow_quit)
2898 { 2496 {
2899 #ifdef VMS
2900 return vms_write (fildes, buf, nbyte);
2901 #else
2902 int rtnval; 2497 int rtnval;
2903 int bytes_written = 0; 2498 int bytes_written = 0;
2904 CONST char *b = (CONST char *) buf; 2499 CONST char *b = (CONST char *) buf;
2905 2500
2906 /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */ 2501 /* No harm in looping regardless of the INTERRUPTIBLE_IO setting. */
2921 b += rtnval; 2516 b += rtnval;
2922 nbyte -= rtnval; 2517 nbyte -= rtnval;
2923 bytes_written += rtnval; 2518 bytes_written += rtnval;
2924 } 2519 }
2925 return (bytes_written); 2520 return (bytes_written);
2926 #endif
2927 } 2521 }
2928 2522
2929 #ifdef ENCAPSULATE_WRITE 2523 #ifdef ENCAPSULATE_WRITE
2930 int 2524 int
2931 sys_write (int fildes, CONST void *buf, unsigned int nbyte) 2525 sys_write (int fildes, CONST void *buf, unsigned int nbyte)
3033 b += size*rtnval; 2627 b += size*rtnval;
3034 nitem -= rtnval; 2628 nitem -= rtnval;
3035 items_written += rtnval; 2629 items_written += rtnval;
3036 } 2630 }
3037 return (items_written); 2631 return (items_written);
3038 #elif defined (VMS)
3039 return vms_fwrite (ptr, size, nitem, stream);
3040 #else 2632 #else
3041 return fwrite (ptr, size, nitem, stream); 2633 return fwrite (ptr, size, nitem, stream);
3042 #endif 2634 #endif
3043 } 2635 }
3044 #endif /* ENCAPSULATE_FWRITE */ 2636 #endif /* ENCAPSULATE_FWRITE */
3170 #ifdef ENCAPSULATE_ACCESS 2762 #ifdef ENCAPSULATE_ACCESS
3171 int 2763 int
3172 sys_access (CONST char *path, int mode) 2764 sys_access (CONST char *path, int mode)
3173 { 2765 {
3174 PATHNAME_CONVERT_OUT (path); 2766 PATHNAME_CONVERT_OUT (path);
3175 #ifdef VMS
3176 return vms_access (path, mode);
3177 #else
3178 return access (path, mode); 2767 return access (path, mode);
3179 #endif
3180 } 2768 }
3181 #endif /* ENCAPSULATE_ACCESS */ 2769 #endif /* ENCAPSULATE_ACCESS */
3182 2770
3183 2771
3184 #ifdef HAVE_EACCESS 2772 #ifdef HAVE_EACCESS
3884 sys_close (dirp->dd_fd); 3472 sys_close (dirp->dd_fd);
3885 xfree (dirp); 3473 xfree (dirp);
3886 } 3474 }
3887 3475
3888 3476
3889 #ifndef VMS
3890 #define DIRSIZ 14 3477 #define DIRSIZ 14
3891 struct olddir 3478 struct olddir
3892 { 3479 {
3893 ino_t od_ino; /* inode */ 3480 ino_t od_ino; /* inode */
3894 char od_name[DIRSIZ]; /* filename */ 3481 char od_name[DIRSIZ]; /* filename */
3895 }; 3482 };
3896 #endif /* not VMS */
3897 3483
3898 static struct direct dir_static; /* simulated directory contents */ 3484 static struct direct dir_static; /* simulated directory contents */
3899 3485
3900 /* ARGUSED */ 3486 /* ARGUSED */
3901 struct direct * 3487 struct direct *
3902 readdir (DIR *dirp) /* stream from opendir */ 3488 readdir (DIR *dirp) /* stream from opendir */
3903 { 3489 {
3904 #ifndef VMS
3905 struct olddir *dp; /* -> directory data */ 3490 struct olddir *dp; /* -> directory data */
3906 #else /* VMS */
3907 struct dir$_name *dp; /* -> directory data */
3908 struct dir$_version *dv; /* -> version data */
3909 #endif /* VMS */
3910 3491
3911 for (; ;) 3492 for (; ;)
3912 { 3493 {
3913 if (dirp->dd_loc >= dirp->dd_size) 3494 if (dirp->dd_loc >= dirp->dd_size)
3914 dirp->dd_loc = dirp->dd_size = 0; 3495 dirp->dd_loc = dirp->dd_size = 0;
3915 3496
3916 if (dirp->dd_size == 0 /* refill buffer */ 3497 if (dirp->dd_size == 0 /* refill buffer */
3917 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0) 3498 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3918 return 0; 3499 return 0;
3919 3500
3920 #ifndef VMS
3921 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc]; 3501 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
3922 dirp->dd_loc += sizeof (struct olddir); 3502 dirp->dd_loc += sizeof (struct olddir);
3923 3503
3924 if (dp->od_ino != 0) /* not deleted entry */ 3504 if (dp->od_ino != 0) /* not deleted entry */
3925 { 3505 {
3930 dir_static.d_reclen = sizeof (struct direct) 3510 dir_static.d_reclen = sizeof (struct direct)
3931 - MAXNAMLEN + 3 3511 - MAXNAMLEN + 3
3932 + dir_static.d_namlen - dir_static.d_namlen % 4; 3512 + dir_static.d_namlen - dir_static.d_namlen % 4;
3933 return &dir_static; /* -> simulated structure */ 3513 return &dir_static; /* -> simulated structure */
3934 } 3514 }
3935 #else /* VMS */ 3515 }
3936 dp = (struct dir$_name *) dirp->dd_buf; 3516 }
3937 if (dirp->dd_loc == 0) 3517
3938 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
3939 : dp->dir$b_namecount;
3940 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
3941 dir_static.d_ino = dv->dir$w_fid_num;
3942 dir_static.d_namlen = dp->dir$b_namecount;
3943 dir_static.d_reclen = sizeof (struct direct)
3944 - MAXNAMLEN + 3
3945 + dir_static.d_namlen - dir_static.d_namlen % 4;
3946 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3947 dir_static.d_name[dir_static.d_namlen] = '\0';
3948 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
3949 return &dir_static;
3950 #endif /* VMS */
3951 }
3952 }
3953
3954 #ifdef VMS
3955 /* readdirver is just like readdir except it returns all versions of a file
3956 as separate entries. */
3957
3958 /* ARGUSED */
3959 struct direct *
3960 readdirver (DIR *dirp) /* stream from opendir */
3961 {
3962 struct dir$_name *dp; /* -> directory data */
3963 struct dir$_version *dv; /* -> version data */
3964
3965 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
3966 dirp->dd_loc = dirp->dd_size = 0;
3967
3968 if (dirp->dd_size == 0 /* refill buffer */
3969 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
3970 return 0;
3971
3972 dp = (struct dir$_name *) dirp->dd_buf;
3973 if (dirp->dd_loc == 0)
3974 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
3975 : dp->dir$b_namecount;
3976 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
3977 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
3978 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
3979 dir_static.d_namlen = strlen (dir_static.d_name);
3980 dir_static.d_ino = dv->dir$w_fid_num;
3981 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
3982 + dir_static.d_namlen - dir_static.d_namlen % 4;
3983 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
3984 return &dir_static;
3985 }
3986
3987 #endif /* VMS */
3988 3518
3989 #endif /* NONSYSTEM_DIR_LIBRARY */ 3519 #endif /* NONSYSTEM_DIR_LIBRARY */
3990 3520
3991 3521
3992 /* mkdir and rmdir functions, for systems which don't have them. */ 3522 /* mkdir and rmdir functions, for systems which don't have them. */
4147 } 3677 }
4148 3678
4149 #endif /* USE_DL_STUBS */ 3679 #endif /* USE_DL_STUBS */
4150 3680
4151 3681
4152 /************************************************************************/
4153 /* VMS emulation of system calls */
4154 /************************************************************************/
4155
4156 #ifdef VMS
4157 #include "vms-pwd.h"
4158 #include <acldef.h>
4159 #include <chpdef.h>
4160 #include <jpidef.h>
4161
4162 /* Return as a string the VMS error string pertaining to STATUS.
4163 Reuses the same static buffer each time it is called. */
4164
4165 char *
4166 vmserrstr (int status) /* VMS status code */
4167 {
4168 int bufadr[2];
4169 short len;
4170 static char buf[257];
4171
4172 bufadr[0] = sizeof buf - 1;
4173 bufadr[1] = (int) buf;
4174 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
4175 return "untranslatable VMS error status";
4176 buf[len] = '\0';
4177 return buf;
4178 }
4179
4180 #ifdef access
4181 #undef access
4182
4183 /* The following is necessary because 'access' emulation by VMS C (2.0) does
4184 * not work correctly. (It also doesn't work well in version 2.3.)
4185 */
4186
4187 #ifdef VMS4_4
4188
4189 #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
4190 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
4191
4192 typedef union {
4193 struct {
4194 unsigned short s_buflen;
4195 unsigned short s_code;
4196 char *s_bufadr;
4197 unsigned short *s_retlenadr;
4198 } s;
4199 int end;
4200 } item;
4201 #define buflen s.s_buflen
4202 #define code s.s_code
4203 #define bufadr s.s_bufadr
4204 #define retlenadr s.s_retlenadr
4205
4206 #define R_OK 4 /* test for read permission */
4207 #define W_OK 2 /* test for write permission */
4208 #define X_OK 1 /* test for execute (search) permission */
4209 #define F_OK 0 /* test for presence of file */
4210
4211 int
4212 vms_access (CONST char *path, int mode)
4213 {
4214 static char *user = NULL;
4215 char dir_fn[512];
4216
4217 /* translate possible directory spec into .DIR file name, so brain-dead
4218 * access can treat the directory like a file. */
4219 if (directory_file_name (path, dir_fn))
4220 path = dir_fn;
4221
4222 if (mode == F_OK)
4223 return access (path, mode);
4224 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
4225 return -1;
4226 {
4227 int stat;
4228 int flags;
4229 int acces;
4230 unsigned short int dummy;
4231 item itemlst[3];
4232 static int constant = ACL$C_FILE;
4233 DESCRIPTOR (path_desc, path);
4234 DESCRIPTOR (user_desc, user);
4235
4236 flags = 0;
4237 acces = 0;
4238 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
4239 return stat;
4240 if (mode & R_OK)
4241 acces |= CHP$M_READ;
4242 if (mode & W_OK)
4243 acces |= CHP$M_WRITE;
4244 itemlst[0].buflen = sizeof (int);
4245 itemlst[0].code = CHP$_FLAGS;
4246 itemlst[0].bufadr = (char *) &flags;
4247 itemlst[0].retlenadr = &dummy;
4248 itemlst[1].buflen = sizeof (int);
4249 itemlst[1].code = CHP$_ACCESS;
4250 itemlst[1].bufadr = (char *) &acces;
4251 itemlst[1].retlenadr = &dummy;
4252 itemlst[2].end = CHP$_END;
4253 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
4254 return stat == SS$_NORMAL ? 0 : -1;
4255 }
4256 }
4257
4258 #else /* not VMS4_4 */
4259
4260 #include <prvdef.h>
4261 #define ACE$M_WRITE 2
4262 #define ACE$C_KEYID 1
4263
4264 static unsigned short vms_memid, vms_grpid;
4265 static unsigned int vms_uic;
4266
4267 /* Called from init_sys_modes, so it happens not very often
4268 but at least each time Emacs is loaded. */
4269 sys_access_reinit (void)
4270 {
4271 vms_uic = 0;
4272 }
4273
4274 int
4275 vms_access (CONST char *filename, int type)
4276 {
4277 struct FAB fab;
4278 struct XABPRO xab;
4279 int status, size, i, typecode, acl_controlled;
4280 unsigned int *aclptr, *aclend, aclbuf[60];
4281 union prvdef prvmask;
4282
4283 /* Get UIC and GRP values for protection checking. */
4284 if (vms_uic == 0)
4285 {
4286 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &vms_uic, 0, 0);
4287 if (! (status & 1))
4288 return -1;
4289 vms_memid = vms_uic & 0xFFFF;
4290 vms_grpid = vms_uic >> 16;
4291 }
4292
4293 if (type != 2) /* not checking write access */
4294 return access (filename, type);
4295
4296 /* Check write protection. */
4297
4298 #define CHECKPRIV(bit) (prvmask.bit)
4299 #define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
4300
4301 /* Find privilege bits */
4302 status = SYS$SETPRV (0, 0, 0, prvmask);
4303 if (! (status & 1))
4304 error ("Unable to find privileges: %s", vmserrstr (status));
4305 if (CHECKPRIV (PRV$V_BYPASS))
4306 return 0; /* BYPASS enabled */
4307 fab = cc$rms_fab;
4308 fab.fab$b_fac = FAB$M_GET;
4309 fab.fab$l_fna = filename;
4310 fab.fab$b_fns = strlen (filename);
4311 fab.fab$l_xab = &xab;
4312 xab = cc$rms_xabpro;
4313 xab.xab$l_aclbuf = aclbuf;
4314 xab.xab$w_aclsiz = sizeof (aclbuf);
4315 status = SYS$OPEN (&fab, 0, 0);
4316 if (! (status & 1))
4317 return -1;
4318 SYS$CLOSE (&fab, 0, 0);
4319 /* Check system access */
4320 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
4321 return 0;
4322 /* Check ACL entries, if any */
4323 acl_controlled = 0;
4324 if (xab.xab$w_acllen > 0)
4325 {
4326 aclptr = aclbuf;
4327 aclend = &aclbuf[xab.xab$w_acllen / 4];
4328 while (*aclptr && aclptr < aclend)
4329 {
4330 size = (*aclptr & 0xff) / 4;
4331 typecode = (*aclptr >> 8) & 0xff;
4332 if (typecode == ACE$C_KEYID)
4333 for (i = size - 1; i > 1; i--)
4334 if (aclptr[i] == vms_uic)
4335 {
4336 acl_controlled = 1;
4337 if (aclptr[1] & ACE$M_WRITE)
4338 return 0; /* Write access through ACL */
4339 }
4340 aclptr = &aclptr[size];
4341 }
4342 if (acl_controlled) /* ACL specified, prohibits write access */
4343 return -1;
4344 }
4345 /* No ACL entries specified, check normal protection */
4346 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
4347 return 0;
4348 if (WRITEABLE (XAB$V_GRP) &&
4349 (unsigned short) (xab.xab$l_uic >> 16) == vms_grpid)
4350 return 0; /* Group writeable */
4351 if (WRITEABLE (XAB$V_OWN) &&
4352 (xab.xab$l_uic & 0xFFFF) == vms_memid)
4353 return 0; /* Owner writeable */
4354
4355 return -1; /* Not writeable */
4356 }
4357 #endif /* not VMS4_4 */
4358 #endif /* access */
4359
4360 static char vtbuf[NAM$C_MAXRSS+1];
4361
4362 /* translate a vms file spec to a unix path */
4363 char *
4364 sys_translate_vms (char *vfile)
4365 {
4366 char * p;
4367 char * targ;
4368
4369 if (!vfile)
4370 return 0;
4371
4372 targ = vtbuf;
4373
4374 /* leading device or logical name is a root directory */
4375 if (p = strchr (vfile, ':'))
4376 {
4377 *targ++ = '/';
4378 while (vfile < p)
4379 *targ++ = *vfile++;
4380 vfile++;
4381 *targ++ = '/';
4382 }
4383 p = vfile;
4384 if (*p == '[' || *p == '<')
4385 {
4386 while (*++vfile != *p + 2)
4387 switch (*vfile)
4388 {
4389 case '.':
4390 if (vfile[-1] == *p)
4391 *targ++ = '.';
4392 *targ++ = '/';
4393 break;
4394
4395 case '-':
4396 *targ++ = '.';
4397 *targ++ = '.';
4398 break;
4399
4400 default:
4401 *targ++ = *vfile;
4402 break;
4403 }
4404 vfile++;
4405 *targ++ = '/';
4406 }
4407 while (*vfile)
4408 *targ++ = *vfile++;
4409
4410 return vtbuf;
4411 }
4412
4413 static char utbuf[NAM$C_MAXRSS+1];
4414
4415 /* translate a unix path to a VMS file spec */
4416 char *
4417 sys_translate_unix (char *ufile)
4418 {
4419 int slash_seen = 0;
4420 char *p;
4421 char * targ;
4422
4423 if (!ufile)
4424 return 0;
4425
4426 targ = utbuf;
4427
4428 if (*ufile == '/')
4429 {
4430 ufile++;
4431 }
4432
4433 while (*ufile)
4434 {
4435 switch (*ufile)
4436 {
4437 case '/':
4438 if (slash_seen)
4439 if (strchr (&ufile[1], '/'))
4440 *targ++ = '.';
4441 else
4442 *targ++ = ']';
4443 else
4444 {
4445 *targ++ = ':';
4446 if (strchr (&ufile[1], '/'))
4447 *targ++ = '[';
4448 slash_seen = 1;
4449 }
4450 break;
4451
4452 case '.':
4453 if (strncmp (ufile, "./", 2) == 0)
4454 {
4455 if (!slash_seen)
4456 {
4457 *targ++ = '[';
4458 slash_seen = 1;
4459 }
4460 ufile++; /* skip the dot */
4461 if (strchr (&ufile[1], '/'))
4462 *targ++ = '.';
4463 else
4464 *targ++ = ']';
4465 }
4466 else if (strncmp (ufile, "../", 3) == 0)
4467 {
4468 if (!slash_seen)
4469 {
4470 *targ++ = '[';
4471 slash_seen = 1;
4472 }
4473 *targ++ = '-';
4474 ufile += 2; /* skip the dots */
4475 if (strchr (&ufile[1], '/'))
4476 *targ++ = '.';
4477 else
4478 *targ++ = ']';
4479 }
4480 else
4481 *targ++ = *ufile;
4482 break;
4483
4484 default:
4485 *targ++ = *ufile;
4486 break;
4487 }
4488 ufile++;
4489 }
4490 *targ = '\0';
4491
4492 return utbuf;
4493 }
4494
4495 char *
4496 getwd (char *pathname)
4497 {
4498 char *ptr;
4499 strcpy (pathname, egetenv ("PATH"));
4500
4501 ptr = pathname;
4502 while (*ptr)
4503 {
4504 /* #### This is evil. Smashes (shared) result of egetenv */
4505 *ptr = toupper (* (unsigned char *) ptr);
4506 ptr++;
4507 }
4508 return pathname;
4509 }
4510
4511 int
4512 getppid (void)
4513 {
4514 long item_code = JPI$_OWNER;
4515 unsigned long parent_id;
4516 int status;
4517
4518 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
4519 {
4520 errno = EVMSERR;
4521 vaxc$errno = status;
4522 return -1;
4523 }
4524 return parent_id;
4525 }
4526
4527 #undef getuid
4528 unsigned int
4529 sys_getuid (void)
4530 {
4531 return (getgid () << 16) | getuid ();
4532 }
4533
4534 int
4535 vms_read (int fildes, CONST void *buf, unsigned int nbyte)
4536 {
4537 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
4538 }
4539
4540 #if 0
4541 int
4542 vms_write (int fildes, CONST void *buf, unsigned int nbyte)
4543 {
4544 int nwrote, rtnval = 0;
4545
4546 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0)
4547 {
4548 nbyte -= nwrote;
4549 buf += nwrote;
4550 rtnval += nwrote;
4551 }
4552 if (nwrote < 0)
4553 return rtnval ? rtnval : -1;
4554 if ((nwrote = write (fildes, buf, nbyte)) < 0)
4555 return rtnval ? rtnval : -1;
4556 return (rtnval + nwrote);
4557 }
4558 #endif /* 0 */
4559
4560 /*
4561 * VAX/VMS VAX C RTL really loses. It insists that records
4562 * end with a newline (carriage return) character, and if they
4563 * don't it adds one (nice of it isn't it!)
4564 *
4565 * Thus we do this stupidity below.
4566 */
4567
4568 int
4569 vms_write (int fildes, CONST void *buf, unsigned int nbytes)
4570 {
4571 char *p;
4572 char *e;
4573 int sum = 0;
4574 struct stat st;
4575
4576 fstat (fildes, &st);
4577 p = buf;
4578 while (nbytes > 0)
4579 {
4580 int len, retval;
4581
4582 /* Handle fixed-length files with carriage control. */
4583 if (st.st_fab_rfm == FAB$C_FIX
4584 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
4585 {
4586 len = st.st_fab_mrs;
4587 retval = write (fildes, p, min (len, nbytes));
4588 if (retval != len)
4589 return -1;
4590 retval++; /* This skips the implied carriage control */
4591 }
4592 else
4593 {
4594 e = p + min (MAXIOSIZE, nbytes) - 1;
4595 while (*e != '\n' && e > p) e--;
4596 if (p == e) /* Ok.. so here we add a newline... sigh. */
4597 e = p + min (MAXIOSIZE, nbytes) - 1;
4598 len = e + 1 - p;
4599 retval = write (fildes, p, len);
4600 if (retval != len)
4601 return -1;
4602 }
4603 p += retval;
4604 sum += retval;
4605 nbytes -= retval;
4606 }
4607 return sum;
4608 }
4609
4610 /* Create file NEW copying its attributes from file OLD. If
4611 OLD is 0 or does not exist, create based on the value of
4612 vms_stmlf_recfm. */
4613
4614 /* Protection value the file should ultimately have.
4615 Set by create_copy_attrs, and use by rename_sansversions. */
4616 static unsigned short int vms_fab_final_pro;
4617
4618 int
4619 creat_copy_attrs (char *old, char *new)
4620 {
4621 struct FAB fab = cc$rms_fab;
4622 struct XABPRO xabpro;
4623 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
4624 extern int vms_stmlf_recfm;
4625
4626 if (old)
4627 {
4628 fab.fab$b_fac = FAB$M_GET;
4629 fab.fab$l_fna = old;
4630 fab.fab$b_fns = strlen (old);
4631 fab.fab$l_xab = (char *) &xabpro;
4632 xabpro = cc$rms_xabpro;
4633 xabpro.xab$l_aclbuf = aclbuf;
4634 xabpro.xab$w_aclsiz = sizeof aclbuf;
4635 /* Call $OPEN to fill in the fab & xabpro fields. */
4636 if (SYS$OPEN (&fab, 0, 0) & 1)
4637 {
4638 SYS$CLOSE (&fab, 0, 0);
4639 fab.fab$l_alq = 0; /* zero the allocation quantity */
4640 if (xabpro.xab$w_acllen > 0)
4641 {
4642 if (xabpro.xab$w_acllen > sizeof aclbuf)
4643 /* If the acl buffer was too short, redo open with longer one.
4644 Wouldn't need to do this if there were some system imposed
4645 limit on the size of an ACL, but I can't find any such. */
4646 {
4647 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
4648 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
4649 if (SYS$OPEN (&fab, 0, 0) & 1)
4650 SYS$CLOSE (&fab, 0, 0);
4651 else
4652 old = 0;
4653 }
4654 }
4655 else
4656 xabpro.xab$l_aclbuf = 0;
4657 }
4658 else
4659 old = 0;
4660 }
4661 fab.fab$l_fna = new;
4662 fab.fab$b_fns = strlen (new);
4663 if (!old)
4664 {
4665 fab.fab$l_xab = 0;
4666 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
4667 fab.fab$b_rat = FAB$M_CR;
4668 }
4669
4670 /* Set the file protections such that we will be able to manipulate
4671 this file. Once we are done writing and renaming it, we will set
4672 the protections back. */
4673 if (old)
4674 vms_fab_final_pro = xabpro.xab$w_pro;
4675 else
4676 SYS$SETDFPROT (0, &vms_fab_final_pro);
4677 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
4678
4679 /* Create the new file with either default attrs or attrs copied
4680 from old file. */
4681 if (!(SYS$CREATE (&fab, 0, 0) & 1))
4682 return -1;
4683 SYS$CLOSE (&fab, 0, 0);
4684 /* As this is a "replacement" for creat, return a file descriptor
4685 opened for writing. */
4686 return open (new, O_WRONLY);
4687 }
4688
4689 int
4690 vms_creat (CONST char *path, int mode, ...)
4691 {
4692 int rfd; /* related file descriptor */
4693 int fd; /* Our new file descriptor */
4694 int count;
4695 struct stat st_buf;
4696 char rfm[12];
4697 char rat[15];
4698 char mrs[13];
4699 char fsz[13];
4700 extern int vms_stmlf_recfm;
4701
4702 /* #### there was some weird machine-dependent code to determine how many
4703 arguments were passed to this function. This certainly won't work
4704 under ANSI C. */
4705 if (count > 2)
4706 rfd = fix this;
4707 if (count > 2)
4708 {
4709 /* Use information from the related file descriptor to set record
4710 format of the newly created file. */
4711 fstat (rfd, &st_buf);
4712 switch (st_buf.st_fab_rfm)
4713 {
4714 case FAB$C_FIX:
4715 strcpy (rfm, "rfm = fix");
4716 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
4717 strcpy (rat, "rat = ");
4718 if (st_buf.st_fab_rat & FAB$M_CR)
4719 strcat (rat, "cr");
4720 else if (st_buf.st_fab_rat & FAB$M_FTN)
4721 strcat (rat, "ftn");
4722 else if (st_buf.st_fab_rat & FAB$M_PRN)
4723 strcat (rat, "prn");
4724 if (st_buf.st_fab_rat & FAB$M_BLK)
4725 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4726 strcat (rat, ", blk");
4727 else
4728 strcat (rat, "blk");
4729 return creat (name, 0, rfm, rat, mrs);
4730
4731 case FAB$C_VFC:
4732 strcpy (rfm, "rfm = vfc");
4733 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
4734 strcpy (rat, "rat = ");
4735 if (st_buf.st_fab_rat & FAB$M_CR)
4736 strcat (rat, "cr");
4737 else if (st_buf.st_fab_rat & FAB$M_FTN)
4738 strcat (rat, "ftn");
4739 else if (st_buf.st_fab_rat & FAB$M_PRN)
4740 strcat (rat, "prn");
4741 if (st_buf.st_fab_rat & FAB$M_BLK)
4742 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4743 strcat (rat, ", blk");
4744 else
4745 strcat (rat, "blk");
4746 return creat (name, 0, rfm, rat, fsz);
4747
4748 case FAB$C_STM:
4749 strcpy (rfm, "rfm = stm");
4750 break;
4751
4752 case FAB$C_STMCR:
4753 strcpy (rfm, "rfm = stmcr");
4754 break;
4755
4756 case FAB$C_STMLF:
4757 strcpy (rfm, "rfm = stmlf");
4758 break;
4759
4760 case FAB$C_UDF:
4761 strcpy (rfm, "rfm = udf");
4762 break;
4763
4764 case FAB$C_VAR:
4765 strcpy (rfm, "rfm = var");
4766 break;
4767 }
4768 strcpy (rat, "rat = ");
4769 if (st_buf.st_fab_rat & FAB$M_CR)
4770 strcat (rat, "cr");
4771 else if (st_buf.st_fab_rat & FAB$M_FTN)
4772 strcat (rat, "ftn");
4773 else if (st_buf.st_fab_rat & FAB$M_PRN)
4774 strcat (rat, "prn");
4775 if (st_buf.st_fab_rat & FAB$M_BLK)
4776 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
4777 strcat (rat, ", blk");
4778 else
4779 strcat (rat, "blk");
4780 }
4781 else
4782 {
4783 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
4784 strcpy (rat, "rat=cr");
4785 }
4786 /* Until the VAX C RTL fixes the many bugs with modes, always use
4787 mode 0 to get the user's default protection. */
4788 fd = creat (name, 0, rfm, rat);
4789 if (fd < 0 && errno == EEXIST)
4790 {
4791 if (unlink (name) < 0)
4792 report_file_error ("delete", build_string (name));
4793 fd = creat (name, 0, rfm, rat);
4794 }
4795 return fd;
4796 }
4797
4798 /* fwrite to stdout is S L O W. Speed it up by using fputc...*/
4799 int
4800 vms_fwrite (CONST void *ptr, int size, int num, FILE *fp)
4801 {
4802 int tot = num * size;
4803
4804 while (tot--)
4805 fputc (* (CONST char *) ptr++, fp);
4806 return (num);
4807 }
4808
4809 /*
4810 * The VMS C library routine creat actually creates a new version of an
4811 * existing file rather than truncating the old version. There are times
4812 * when this is not the desired behavior, for instance, when writing an
4813 * auto save file (you only want one version), or when you don't have
4814 * write permission in the directory containing the file (but the file
4815 * itself is writable). Hence this routine, which is equivalent to
4816 * "close (creat (fn, 0));" on Unix if fn already exists.
4817 */
4818 int
4819 vms_truncate (char *fn)
4820 {
4821 struct FAB xfab = cc$rms_fab;
4822 struct RAB xrab = cc$rms_rab;
4823 int status;
4824
4825 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
4826 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
4827 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
4828 xfab.fab$l_fna = fn;
4829 xfab.fab$b_fns = strlen (fn);
4830 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
4831 xfab.fab$b_dns = 2;
4832 xrab.rab$l_fab = &xfab;
4833
4834 /* This gibberish opens the file, positions to the first record, and
4835 deletes all records from there until the end of file. */
4836 if ((SYS$OPEN (&xfab) & 01) == 01)
4837 {
4838 if ((SYS$CONNECT (&xrab) & 01) == 01 &&
4839 (SYS$FIND (&xrab) & 01) == 01 &&
4840 (SYS$TRUNCATE (&xrab) & 01) == 01)
4841 status = 0;
4842 else
4843 status = -1;
4844 }
4845 else
4846 status = -1;
4847 SYS$CLOSE (&xfab);
4848 return status;
4849 }
4850
4851 /* Define this symbol to actually read SYSUAF.DAT. This requires either
4852 SYSPRV or a readable SYSUAF.DAT. */
4853
4854 #ifdef READ_SYSUAF
4855 /*
4856 * getuaf.c
4857 *
4858 * Routine to read the VMS User Authorization File and return
4859 * a specific user's record.
4860 */
4861
4862 static struct UAF vms_retuaf;
4863
4864 static struct UAF *
4865 get_uaf_name (char *uname)
4866 {
4867 status;
4868 struct FAB uaf_fab;
4869 struct RAB uaf_rab;
4870
4871 uaf_fab = cc$rms_fab;
4872 uaf_rab = cc$rms_rab;
4873 /* initialize fab fields */
4874 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4875 uaf_fab.fab$b_fns = 21;
4876 uaf_fab.fab$b_fac = FAB$M_GET;
4877 uaf_fab.fab$b_org = FAB$C_IDX;
4878 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4879 /* initialize rab fields */
4880 uaf_rab.rab$l_fab = &uaf_fab;
4881 /* open the User Authorization File */
4882 status = SYS$OPEN (&uaf_fab);
4883 if (!(status&1))
4884 {
4885 errno = EVMSERR;
4886 vaxc$errno = status;
4887 return 0;
4888 }
4889 status = SYS$CONNECT (&uaf_rab);
4890 if (!(status&1))
4891 {
4892 errno = EVMSERR;
4893 vaxc$errno = status;
4894 return 0;
4895 }
4896 /* read the requested record - index is in uname */
4897 uaf_rab.rab$l_kbf = uname;
4898 uaf_rab.rab$b_ksz = strlen (uname);
4899 uaf_rab.rab$b_rac = RAB$C_KEY;
4900 uaf_rab.rab$l_ubf = (char *)&vms_retuaf;
4901 uaf_rab.rab$w_usz = sizeof vms_retuaf;
4902 status = SYS$GET (&uaf_rab);
4903 if (!(status&1))
4904 {
4905 errno = EVMSERR;
4906 vaxc$errno = status;
4907 return 0;
4908 }
4909 /* close the User Authorization File */
4910 status = SYS$DISCONNECT (&uaf_rab);
4911 if (!(status&1))
4912 {
4913 errno = EVMSERR;
4914 vaxc$errno = status;
4915 return 0;
4916 }
4917 status = SYS$CLOSE (&uaf_fab);
4918 if (!(status&1))
4919 {
4920 errno = EVMSERR;
4921 vaxc$errno = status;
4922 return 0;
4923 }
4924 return &vms_retuaf;
4925 }
4926
4927 static struct UAF *
4928 get_uaf_uic (unsigned long uic)
4929 {
4930 status;
4931 struct FAB uaf_fab;
4932 struct RAB uaf_rab;
4933
4934 uaf_fab = cc$rms_fab;
4935 uaf_rab = cc$rms_rab;
4936 /* initialize fab fields */
4937 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
4938 uaf_fab.fab$b_fns = 21;
4939 uaf_fab.fab$b_fac = FAB$M_GET;
4940 uaf_fab.fab$b_org = FAB$C_IDX;
4941 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
4942 /* initialize rab fields */
4943 uaf_rab.rab$l_fab = &uaf_fab;
4944 /* open the User Authorization File */
4945 status = SYS$OPEN (&uaf_fab);
4946 if (!(status&1))
4947 {
4948 errno = EVMSERR;
4949 vaxc$errno = status;
4950 return 0;
4951 }
4952 status = SYS$CONNECT (&uaf_rab);
4953 if (!(status&1))
4954 {
4955 errno = EVMSERR;
4956 vaxc$errno = status;
4957 return 0;
4958 }
4959 /* read the requested record - index is in uic */
4960 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
4961 uaf_rab.rab$l_kbf = (char *) &uic;
4962 uaf_rab.rab$b_ksz = sizeof uic;
4963 uaf_rab.rab$b_rac = RAB$C_KEY;
4964 uaf_rab.rab$l_ubf = (char *)&vms_retuaf;
4965 uaf_rab.rab$w_usz = sizeof vms_retuaf;
4966 status = SYS$GET (&uaf_rab);
4967 if (!(status&1))
4968 {
4969 errno = EVMSERR;
4970 vaxc$errno = status;
4971 return 0;
4972 }
4973 /* close the User Authorization File */
4974 status = SYS$DISCONNECT (&uaf_rab);
4975 if (!(status&1))
4976 {
4977 errno = EVMSERR;
4978 vaxc$errno = status;
4979 return 0;
4980 }
4981 status = SYS$CLOSE (&uaf_fab);
4982 if (!(status&1))
4983 {
4984 errno = EVMSERR;
4985 vaxc$errno = status;
4986 return 0;
4987 }
4988 return &vms_retuaf;
4989 }
4990
4991 static struct passwd vms_retpw;
4992
4993 static struct passwd *
4994 cnv_uaf_pw (struct UAF *up)
4995 {
4996 char * ptr;
4997
4998 /* copy these out first because if the username is 32 chars, the next
4999 section will overwrite the first byte of the UIC */
5000 vms_retpw.pw_uid = up->uaf$w_mem;
5001 vms_retpw.pw_gid = up->uaf$w_grp;
5002
5003 /* I suppose this is not the best sytle, to possibly overwrite one
5004 byte beyond the end of the field, but what the heck... */
5005 ptr = &up->uaf$t_username[UAF$S_USERNAME];
5006 while (ptr[-1] == ' ')
5007 ptr--;
5008 *ptr = '\0';
5009 strcpy (vms_retpw.pw_name, up->uaf$t_username);
5010
5011 /* the rest of these are counted ascii strings */
5012 strncpy (vms_retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
5013 vms_retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
5014 strncpy (vms_retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
5015 vms_retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
5016 strncat (vms_retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
5017 vms_retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
5018 strncpy (vms_retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
5019 vms_retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
5020
5021 return &vms_retpw;
5022 }
5023 #else /* not READ_SYSUAF */
5024 static struct passwd vms_retpw;
5025 #endif /* not READ_SYSUAF */
5026
5027 struct passwd *
5028 getpwnam (char *name)
5029 {
5030 #ifdef READ_SYSUAF
5031 struct UAF *up;
5032 #else
5033 char * user;
5034 char * dir;
5035 unsigned char * full;
5036 #endif /* READ_SYSUAF */
5037 char *ptr = name;
5038
5039 while (*ptr)
5040 {
5041 *ptr = toupper (* (unsigned char *) ptr);
5042 ptr++;
5043 }
5044 #ifdef READ_SYSUAF
5045 if (!(up = get_uaf_name (name)))
5046 return 0;
5047 return cnv_uaf_pw (up);
5048 #else
5049 if (strcmp (name, getenv ("USER")) == 0)
5050 {
5051 vms_retpw.pw_uid = getuid ();
5052 vms_retpw.pw_gid = getgid ();
5053 strcpy (vms_retpw.pw_name, name);
5054 if (full = egetenv ("FULLNAME"))
5055 strcpy (vms_retpw.pw_gecos, full);
5056 else
5057 *vms_retpw.pw_gecos = '\0';
5058 strcpy (vms_retpw.pw_dir, egetenv ("HOME"));
5059 *vms_retpw.pw_shell = '\0';
5060 return &vms_retpw;
5061 }
5062 else
5063 return 0;
5064 #endif /* not READ_SYSUAF */
5065 }
5066
5067 struct passwd *
5068 getpwuid (unsigned long uid)
5069 {
5070 #ifdef READ_SYSUAF
5071 struct UAF * up;
5072
5073 if (!(up = get_uaf_uic (uid)))
5074 return 0;
5075 return cnv_uaf_pw (up);
5076 #else
5077 if (uid == sys_getuid ())
5078 return getpwnam (egetenv ("USER"));
5079 else
5080 return 0;
5081 #endif /* not READ_SYSUAF */
5082 }
5083
5084 /* return total address space available to the current process. This is
5085 the sum of the current p0 size, p1 size and free page table entries
5086 available. */
5087 int
5088 vlimit (void)
5089 {
5090 int item_code;
5091 unsigned long free_pages;
5092 unsigned long frep0va;
5093 unsigned long frep1va;
5094 status;
5095
5096 item_code = JPI$_FREPTECNT;
5097 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
5098 {
5099 errno = EVMSERR;
5100 vaxc$errno = status;
5101 return -1;
5102 }
5103 free_pages *= 512;
5104
5105 item_code = JPI$_FREP0VA;
5106 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
5107 {
5108 errno = EVMSERR;
5109 vaxc$errno = status;
5110 return -1;
5111 }
5112 item_code = JPI$_FREP1VA;
5113 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
5114 {
5115 errno = EVMSERR;
5116 vaxc$errno = status;
5117 return -1;
5118 }
5119
5120 return free_pages + frep0va + (0x7fffffff - frep1va);
5121 }
5122
5123 int
5124 define_logical_name (char *varname, char *string)
5125 {
5126 struct dsc$descriptor_s strdsc =
5127 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
5128 struct dsc$descriptor_s envdsc =
5129 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
5130 struct dsc$descriptor_s lnmdsc =
5131 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
5132
5133 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
5134 }
5135
5136 int
5137 delete_logical_name (char *varname)
5138 {
5139 struct dsc$descriptor_s envdsc =
5140 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
5141 struct dsc$descriptor_s lnmdsc =
5142 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
5143
5144 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
5145 }
5146
5147 execvp (void)
5148 {
5149 error ("execvp system call not implemented");
5150 }
5151
5152 int
5153 rename (char *from, char *to)
5154 {
5155 int status;
5156 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
5157 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
5158 char from_esn[NAM$C_MAXRSS];
5159 char to_esn[NAM$C_MAXRSS];
5160
5161 from_fab.fab$l_fna = from;
5162 from_fab.fab$b_fns = strlen (from);
5163 from_fab.fab$l_nam = &from_nam;
5164 from_fab.fab$l_fop = FAB$M_NAM;
5165
5166 from_nam.nam$l_esa = from_esn;
5167 from_nam.nam$b_ess = sizeof from_esn;
5168
5169 to_fab.fab$l_fna = to;
5170 to_fab.fab$b_fns = strlen (to);
5171 to_fab.fab$l_nam = &to_nam;
5172 to_fab.fab$l_fop = FAB$M_NAM;
5173
5174 to_nam.nam$l_esa = to_esn;
5175 to_nam.nam$b_ess = sizeof to_esn;
5176
5177 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
5178
5179 if (status & 1)
5180 return 0;
5181 else
5182 {
5183 if (status == RMS$_DEV)
5184 errno = EXDEV;
5185 else
5186 errno = EVMSERR;
5187 vaxc$errno = status;
5188 return -1;
5189 }
5190 }
5191
5192 /* This function renames a file like `rename', but it strips
5193 the version number from the "to" filename, such that the "to" file is
5194 will always be a new version. It also sets the file protection once it is
5195 finished. The protection that we will use is stored in vms_fab_final_pro,
5196 and was set when we did a creat_copy_attrs to create the file that we
5197 are renaming.
5198
5199 We could use the chmod function, but Eunichs uses 3 bits per user category
5200 to describe the protection, and VMS uses 4 (write and delete are separate
5201 bits). To maintain portability, the VMS implementation of `chmod' wires
5202 the W and D bits together. */
5203
5204
5205 static char vms_file_written[NAM$C_MAXRSS];
5206
5207 int
5208 rename_sans_version (char *from, char *to)
5209 {
5210 short int chan;
5211 int stat;
5212 short int iosb[4];
5213 int status;
5214 struct fibdef fib;
5215 struct FAB to_fab = cc$rms_fab;
5216 struct NAM to_nam = cc$rms_nam;
5217 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
5218 struct dsc$descriptor fib_attr[2]
5219 = {{sizeof (vms_fab_final_pro),ATR$C_FPRO,0,(char*) &vms_fab_final_pro},{0,0,0,0}};
5220 char to_esn[NAM$C_MAXRSS];
5221
5222 $DESCRIPTOR (disk,to_esn);
5223
5224 memset (&fib, 0, sizeof (fib));
5225
5226 to_fab.fab$l_fna = to;
5227 to_fab.fab$b_fns = strlen (to);
5228 to_fab.fab$l_nam = &to_nam;
5229 to_fab.fab$l_fop = FAB$M_NAM;
5230
5231 to_nam.nam$l_esa = to_esn;
5232 to_nam.nam$b_ess = sizeof to_esn;
5233
5234 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
5235
5236 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
5237 *(to_nam.nam$l_ver) = '\0';
5238
5239 stat = rename (from, to_esn);
5240 if (stat < 0)
5241 return stat;
5242
5243 strcpy (vms_file_written, to_esn);
5244
5245 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
5246 to_fab.fab$b_fns = strlen (vms_file_written);
5247
5248 /* Now set the file protection to the correct value */
5249 SYS$OPEN (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
5250
5251 /* Copy these fields into the fib */
5252 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
5253 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
5254 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
5255
5256 SYS$CLOSE (&to_fab, 0, 0);
5257
5258 stat = SYS$ASSIGN (&disk, &chan, 0, 0); /* open a channel to the disk */
5259 if (!stat)
5260 LIB$SIGNAL (stat);
5261 stat = SYS$QIOW (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
5262 0, 0, 0, &fib_attr, 0);
5263 if (!stat)
5264 LIB$SIGNAL (stat);
5265 stat = SYS$DASSGN (chan);
5266 if (!stat)
5267 LIB$SIGNAL (stat);
5268 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
5269 return 0;
5270 }
5271
5272 int
5273 link (char *file, char *new)
5274 {
5275 status;
5276 struct FAB fab;
5277 struct NAM nam;
5278 unsigned short fid[3];
5279 char esa[NAM$C_MAXRSS];
5280
5281 fab = cc$rms_fab;
5282 fab.fab$l_fop = FAB$M_OFP;
5283 fab.fab$l_fna = file;
5284 fab.fab$b_fns = strlen (file);
5285 fab.fab$l_nam = &nam;
5286
5287 nam = cc$rms_nam;
5288 nam.nam$l_esa = esa;
5289 nam.nam$b_ess = NAM$C_MAXRSS;
5290
5291 status = SYS$PARSE (&fab);
5292 if ((status & 1) == 0)
5293 {
5294 errno = EVMSERR;
5295 vaxc$errno = status;
5296 return -1;
5297 }
5298 status = SYS$SEARCH (&fab);
5299 if ((status & 1) == 0)
5300 {
5301 errno = EVMSERR;
5302 vaxc$errno = status;
5303 return -1;
5304 }
5305
5306 fid[0] = nam.nam$w_fid[0];
5307 fid[1] = nam.nam$w_fid[1];
5308 fid[2] = nam.nam$w_fid[2];
5309
5310 fab.fab$l_fna = new;
5311 fab.fab$b_fns = strlen (new);
5312
5313 status = SYS$PARSE (&fab);
5314 if ((status & 1) == 0)
5315 {
5316 errno = EVMSERR;
5317 vaxc$errno = status;
5318 return -1;
5319 }
5320
5321 nam.nam$w_fid[0] = fid[0];
5322 nam.nam$w_fid[1] = fid[1];
5323 nam.nam$w_fid[2] = fid[2];
5324
5325 nam.nam$l_esa = nam.nam$l_name;
5326 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
5327
5328 status = SYS$ENTER (&fab);
5329 if ((status & 1) == 0)
5330 {
5331 errno = EVMSERR;
5332 vaxc$errno = status;
5333 return -1;
5334 }
5335
5336 return 0;
5337 }
5338
5339 #ifdef getenv
5340 /* If any place else asks for the TERM variable,
5341 allow it to be overridden with the EMACS_TERM variable
5342 before attempting to translate the logical name TERM. As a last
5343 resort, ask for VAX C's special idea of the TERM variable. */
5344 #undef getenv
5345 char *
5346 sys_getenv (char *name)
5347 {
5348 char *val;
5349 static char buf[256];
5350 static struct dsc$descriptor_s equiv
5351 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
5352 static struct dsc$descriptor_s d_name
5353 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
5354 short eqlen;
5355
5356 if (!strcmp (name, "TERM"))
5357 {
5358 val = (char *) getenv ("EMACS_TERM");
5359 if (val)
5360 return val;
5361 }
5362
5363 d_name.dsc$w_length = strlen (name);
5364 d_name.dsc$a_pointer = name;
5365 if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1)
5366 {
5367 char *str = (char *) xmalloc (eqlen + 1);
5368 memcpy (str, buf, eqlen);
5369 str[eqlen] = '\0';
5370 /* This is a storage leak, but a pain to fix. With luck,
5371 no one will ever notice. */
5372 return str;
5373 }
5374 return (char *) getenv (name);
5375 }
5376 #endif /* getenv */
5377
5378 #ifdef abort
5379 /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
5380 to force a call on the debugger from within the image. */
5381 #undef abort
5382 sys_abort (void)
5383 {
5384 reset_all_consoles ();
5385 LIB$SIGNAL (SS$_DEBUG);
5386 }
5387 #endif /* abort */
5388
5389 #if 0 /* Apparently unused */
5390 /* The standard `sleep' routine works some other way
5391 and it stops working if you have ever quit out of it.
5392 This one continues to work. */
5393
5394 void
5395 sys_sleep (int timeval)
5396 {
5397 int time [2];
5398 static int zero = 0;
5399 static int large = -10000000;
5400
5401 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
5402
5403 SYS$CANTIM (1, 0);
5404 if (SYS$SETIMR (vms_timer_ef, time, 0, 1) & 1) /* Set timer */
5405 SYS$WAITFR (vms_timer_ef); /* Wait for timer expiry only */
5406 }
5407 #endif /* 0 */
5408
5409 void
5410 bzero (REGISTER char *b, REGISTER int length)
5411 {
5412 short zero = 0;
5413 long max_str = 65535;
5414
5415 while (length > max_str) {
5416 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5417 length -= max_str;
5418 b += max_str;
5419 }
5420 max_str = length;
5421 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
5422 }
5423
5424 /* Saying `void' requires a declaration, above, where bcopy is used
5425 and that declaration causes pain for systems where bcopy is a macro. */
5426 bcopy (REGISTER char *b1, REGISTER char *b2, REGISTER int length)
5427 {
5428 long max_str = 65535;
5429
5430 while (length > max_str) {
5431 (void) LIB$MOVC3 (&max_str, b1, b2);
5432 length -= max_str;
5433 b1 += max_str;
5434 b2 += max_str;
5435 }
5436 max_str = length;
5437 (void) LIB$MOVC3 (&length, b1, b2);
5438 }
5439
5440 int
5441 bcmp (REGISTER char *b1, REGISTER char *b2, REGISTER int length)
5442 /* This could be a macro! */
5443 {
5444 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
5445 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
5446
5447 return STR$COMPARE (&src1, &src2);
5448 }
5449
5450 #endif /* VMS */
5451 3682
5452 #ifndef HAVE_STRCASECMP 3683 #ifndef HAVE_STRCASECMP
5453 /* 3684 /*
5454 * From BSD 3685 * From BSD
5455 */ 3686 */