1 /* Interfaces to system-dependent kernel and library entries.
   2    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
   3                  2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
   4                  Free Software Foundation, Inc.
   5 
   6 This file is part of GNU Emacs.
   7 
   8 GNU Emacs is free software: you can redistribute it and/or modify
   9 it under the terms of the GNU General Public License as published by
  10 the Free Software Foundation, either version 3 of the License, or
  11 (at your option) any later version.
  12 
  13 GNU Emacs is distributed in the hope that it will be useful,
  14 but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 GNU General Public License for more details.
  17 
  18 You should have received a copy of the GNU General Public License
  19 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
  20 
  21 #ifdef HAVE_CONFIG_H
  22 #include <config.h>
  23 #endif
  24 
  25 #include <ctype.h>
  26 #include <signal.h>
  27 #include <stdio.h>
  28 #include <setjmp.h>
  29 #ifdef HAVE_PWD_H
  30 #include <pwd.h>
  31 #include <grp.h>
  32 #endif /* HAVE_PWD_H */
  33 #ifdef HAVE_LIMITS_H
  34 #include <limits.h>
  35 #endif /* HAVE_LIMITS_H */
  36 #ifdef HAVE_UNISTD_H
  37 #include <unistd.h>
  38 #endif
  39 #ifdef HAVE_ALLOCA_H
  40 #include <alloca.h>
  41 #endif /* HAVE_ALLOCA_H */
  42 
  43 #include "lisp.h"
  44 /* Including stdlib.h isn't necessarily enough to get srandom
  45    declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2.  */
  46 
  47 /* The w32 build defines select stuff in w32.h, which is included by
  48    sys/select.h (included below).   */
  49 #ifndef WINDOWSNT
  50 #include "sysselect.h"
  51 #endif
  52 
  53 #include "blockinput.h"
  54 
  55 #ifdef WINDOWSNT
  56 #define read sys_read
  57 #define write sys_write
  58 #include <windows.h>
  59 #ifndef NULL
  60 #define NULL 0
  61 #endif
  62 #endif /* not WINDOWSNT */
  63 
  64 /* Does anyone other than VMS need this? */
  65 #ifndef fwrite
  66 #define sys_fwrite fwrite
  67 #else
  68 #undef fwrite
  69 #endif
  70 
  71 #include <sys/types.h>
  72 #include <sys/stat.h>
  73 #include <errno.h>
  74 
  75 #ifdef HAVE_SETPGID
  76 #if !defined (USG)
  77 #undef setpgrp
  78 #define setpgrp setpgid
  79 #endif
  80 #endif
  81 
  82 /* Get SI_SRPC_DOMAIN, if it is available.  */
  83 #ifdef HAVE_SYS_SYSTEMINFO_H
  84 #include <sys/systeminfo.h>
  85 #endif
  86 
  87 #ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
  88 #include <dos.h>
  89 #include "dosfns.h"
  90 #include "msdos.h"
  91 #include <sys/param.h>
  92 
  93 extern int etext;
  94 extern unsigned start __asm__ ("start");
  95 #endif
  96 
  97 #include <sys/file.h>
  98 
  99 #ifdef HAVE_FCNTL_H
 100 #include <fcntl.h>
 101 #endif
 102 
 103 #ifndef MSDOS
 104 #include <sys/ioctl.h>
 105 #endif
 106 
 107 #include "systty.h"
 108 #include "syswait.h"
 109 
 110 #if defined (USG)
 111 #include <sys/utsname.h>
 112 #include <memory.h>
 113 #endif /* USG */
 114 
 115 extern int quit_char;
 116 
 117 #include "keyboard.h"
 118 #include "frame.h"
 119 #include "window.h"
 120 #include "termhooks.h"
 121 #include "termchar.h"
 122 #include "termopts.h"
 123 #include "dispextern.h"
 124 #include "process.h"
 125 #include "cm.h"  /* for reset_sys_modes */
 126 
 127 /* For serial_configure and serial_open.  */
 128 extern Lisp_Object QCport, QCspeed, QCprocess;
 129 extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
 130 extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
 131 
 132 #ifdef WINDOWSNT
 133 #include <direct.h>
 134 /* In process.h which conflicts with the local copy.  */
 135 #define _P_WAIT 0
 136 int _cdecl _spawnlp (int, const char *, const char *, ...);
 137 int _cdecl _getpid (void);
 138 extern char *getwd (char *);
 139 #endif
 140 
 141 #include "syssignal.h"
 142 #include "systime.h"
 143 #ifdef HAVE_UTIME_H
 144 #include <utime.h>
 145 #endif
 146 
 147 #ifndef HAVE_UTIMES
 148 #ifndef HAVE_STRUCT_UTIMBUF
 149 /* We want to use utime rather than utimes, but we couldn't find the
 150    structure declaration.  We'll use the traditional one.  */
 151 struct utimbuf {
 152   long actime;
 153   long modtime;
 154 };
 155 #endif
 156 #endif
 157 
 158 /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
 159 #ifndef LPASS8
 160 #define LPASS8 0
 161 #endif
 162 
 163 static const int baud_convert[] =
 164   {
 165     0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
 166     1800, 2400, 4800, 9600, 19200, 38400
 167   };
 168 
 169 #ifdef HAVE_SPEED_T
 170 #include <termios.h>
 171 #else
 172 #if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
 173 #else
 174 #if defined (HAVE_TERMIOS_H) && defined (GNU_LINUX)
 175 #include <termios.h>
 176 #endif
 177 #endif
 178 #endif
 179 
 180 int emacs_ospeed;
 181 
 182 void croak P_ ((char *)) NO_RETURN;
 183 
 184 /* Temporary used by `sigblock' when defined in terms of signprocmask.  */
 185 
 186 SIGMASKTYPE sigprocmask_set;
 187 
 188 
 189 #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
 190 
 191 /* Return the current working directory.  Returns NULL on errors.
 192    Any other returned value must be freed with free. This is used
 193    only when get_current_dir_name is not defined on the system.  */
 194 char*
 195 get_current_dir_name ()
 196 {
 197   char *buf;
 198   char *pwd;
 199   struct stat dotstat, pwdstat;
 200   /* If PWD is accurate, use it instead of calling getwd.  PWD is
 201      sometimes a nicer name, and using it may avoid a fatal error if a
 202      parent directory is searchable but not readable.  */
 203     if ((pwd = getenv ("PWD")) != 0
 204       && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
 205       && stat (pwd, &pwdstat) == 0
 206       && stat (".", &dotstat) == 0
 207       && dotstat.st_ino == pwdstat.st_ino
 208       && dotstat.st_dev == pwdstat.st_dev
 209 #ifdef MAXPATHLEN
 210       && strlen (pwd) < MAXPATHLEN
 211 #endif
 212       )
 213     {
 214       buf = (char *) malloc (strlen (pwd) + 1);
 215       if (!buf)
 216         return NULL;
 217       strcpy (buf, pwd);
 218     }
 219 #ifdef HAVE_GETCWD
 220   else
 221     {
 222       size_t buf_size = 1024;
 223       buf = (char *) malloc (buf_size);
 224       if (!buf)
 225         return NULL;
 226       for (;;)
 227         {
 228           if (getcwd (buf, buf_size) == buf)
 229             break;
 230           if (errno != ERANGE)
 231             {
 232               int tmp_errno = errno;
 233               free (buf);
 234               errno = tmp_errno;
 235               return NULL;
 236             }
 237           buf_size *= 2;
 238           buf = (char *) realloc (buf, buf_size);
 239           if (!buf)
 240             return NULL;
 241         }
 242     }
 243 #else
 244   else
 245     {
 246       /* We need MAXPATHLEN here.  */
 247       buf = (char *) malloc (MAXPATHLEN + 1);
 248       if (!buf)
 249         return NULL;
 250       if (getwd (buf) == NULL)
 251         {
 252           int tmp_errno = errno;
 253           free (buf);
 254           errno = tmp_errno;
 255           return NULL;
 256         }
 257     }
 258 #endif
 259   return buf;
 260 }
 261 #endif
 262 
 263 
 264 /* Discard pending input on all input descriptors.  */
 265 
 266 void
 267 discard_tty_input ()
 268 {
 269 #ifndef WINDOWSNT
 270   struct emacs_tty buf;
 271 
 272   if (noninteractive)
 273     return;
 274 
 275 #ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
 276   while (dos_keyread () != -1)
 277     ;
 278 #else /* not MSDOS */
 279   {
 280     struct tty_display_info *tty;
 281     for (tty = tty_list; tty; tty = tty->next)
 282       {
 283         if (tty->input)         /* Is the device suspended? */
 284           {
 285             EMACS_GET_TTY (fileno (tty->input), &buf);
 286             EMACS_SET_TTY (fileno (tty->input), &buf, 0);
 287           }
 288       }
 289   }
 290 #endif /* not MSDOS */
 291 #endif /* not WINDOWSNT */
 292 }
 293 
 294 
 295 #ifdef SIGTSTP
 296 
 297 /* Arrange for character C to be read as the next input from
 298    the terminal.
 299    XXX What if we have multiple ttys?
 300 */
 301 
 302 void
 303 stuff_char (char c)
 304 {
 305   if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
 306     return;
 307 
 308 /* Should perhaps error if in batch mode */
 309 #ifdef TIOCSTI
 310   ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
 311 #else /* no TIOCSTI */
 312   error ("Cannot stuff terminal input characters in this version of Unix");
 313 #endif /* no TIOCSTI */
 314 }
 315 
 316 #endif /* SIGTSTP */
 317 
 318 void
 319 init_baud_rate (int fd)
 320 {
 321   if (noninteractive)
 322     emacs_ospeed = 0;
 323   else
 324     {
 325 #ifdef DOS_NT
 326     emacs_ospeed = 15;
 327 #else  /* not DOS_NT */
 328 #ifdef HAVE_TERMIOS
 329       struct termios sg;
 330 
 331       sg.c_cflag = B9600;
 332       tcgetattr (fd, &sg);
 333       emacs_ospeed = cfgetospeed (&sg);
 334 #else /* not TERMIOS */
 335 #ifdef HAVE_TERMIO
 336       struct termio sg;
 337 
 338       sg.c_cflag = B9600;
 339 #ifdef HAVE_TCATTR
 340       tcgetattr (fd, &sg);
 341 #else
 342       ioctl (fd, TCGETA, &sg);
 343 #endif
 344       emacs_ospeed = sg.c_cflag & CBAUD;
 345 #else /* neither TERMIOS nor TERMIO */
 346       struct sgttyb sg;
 347 
 348       sg.sg_ospeed = B9600;
 349       if (ioctl (fd, TIOCGETP, &sg) < 0)
 350         abort ();
 351       emacs_ospeed = sg.sg_ospeed;
 352 #endif /* not HAVE_TERMIO */
 353 #endif /* not HAVE_TERMIOS */
 354 #endif /* not DOS_NT */
 355     }
 356 
 357   baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
 358                ? baud_convert[emacs_ospeed] : 9600);
 359   if (baud_rate == 0)
 360     baud_rate = 1200;
 361 }
 362 
 363 
 364 /*ARGSUSED*/
 365 void
 366 set_exclusive_use (fd)
 367      int fd;
 368 {
 369 #ifdef FIOCLEX
 370   ioctl (fd, FIOCLEX, 0);
 371 #endif
 372   /* Ok to do nothing if this feature does not exist */
 373 }
 374 
 375 #ifndef subprocesses
 376 
 377 wait_without_blocking ()
 378 {
 379   croak ("wait_without_blocking");
 380   synch_process_alive = 0;
 381 }
 382 
 383 #endif /* not subprocesses */
 384 
 385 int wait_debugging;   /* Set nonzero to make following function work under dbx
 386                          (at least for bsd).  */
 387 
 388 SIGTYPE
 389 wait_for_termination_signal ()
 390 {}
 391 
 392 /* Wait for subprocess with process id `pid' to terminate and
 393    make sure it will get eliminated (not remain forever as a zombie) */
 394 
 395 void
 396 wait_for_termination (pid)
 397      int pid;
 398 {
 399   while (1)
 400     {
 401 #ifdef subprocesses
 402 #if defined (BSD_SYSTEM) || defined (HPUX)
 403       /* Note that kill returns -1 even if the process is just a zombie now.
 404          But inevitably a SIGCHLD interrupt should be generated
 405          and child_sig will do wait3 and make the process go away. */
 406       /* There is some indication that there is a bug involved with
 407          termination of subprocesses, perhaps involving a kernel bug too,
 408          but no idea what it is.  Just as a hunch we signal SIGCHLD to see
 409          if that causes the problem to go away or get worse.  */
 410       sigsetmask (sigmask (SIGCHLD));
 411       if (0 > kill (pid, 0))
 412         {
 413           sigsetmask (SIGEMPTYMASK);
 414           kill (getpid (), SIGCHLD);
 415           break;
 416         }
 417       if (wait_debugging)
 418         sleep (1);
 419       else
 420         sigpause (SIGEMPTYMASK);
 421 #else /* not BSD_SYSTEM, and not HPUX version >= 6 */
 422 #ifdef WINDOWSNT
 423       wait (0);
 424       break;
 425 #else /* not WINDOWSNT */
 426       sigblock (sigmask (SIGCHLD));
 427       errno = 0;
 428       if (kill (pid, 0) == -1 && errno == ESRCH)
 429         {
 430           sigunblock (sigmask (SIGCHLD));
 431           break;
 432         }
 433 
 434       sigsuspend (&empty_mask);
 435 #endif /* not WINDOWSNT */
 436 #endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
 437 #else /* not subprocesses */
 438       break;
 439 #endif /* not subprocesses */
 440     }
 441 }
 442 
 443 #ifdef subprocesses
 444 
 445 /*
 446  *      flush any pending output
 447  *      (may flush input as well; it does not matter the way we use it)
 448  */
 449 
 450 void
 451 flush_pending_output (channel)
 452      int channel;
 453 {
 454 #ifdef HAVE_TERMIOS
 455   /* If we try this, we get hit with SIGTTIN, because
 456      the child's tty belongs to the child's pgrp. */
 457 #else
 458 #ifdef TCFLSH
 459   ioctl (channel, TCFLSH, 1);
 460 #else
 461 #ifdef TIOCFLUSH
 462   int zero = 0;
 463   /* 3rd arg should be ignored
 464      but some 4.2 kernels actually want the address of an int
 465      and nonzero means something different.  */
 466   ioctl (channel, TIOCFLUSH, &zero);
 467 #endif
 468 #endif
 469 #endif
 470 }
 471 
 472 /*  Set up the terminal at the other end of a pseudo-terminal that
 473     we will be controlling an inferior through.
 474     It should not echo or do line-editing, since that is done
 475     in Emacs.  No padding needed for insertion into an Emacs buffer.  */
 476 
 477 void
 478 child_setup_tty (out)
 479      int out;
 480 {
 481 #ifndef DOS_NT
 482   struct emacs_tty s;
 483 
 484   EMACS_GET_TTY (out, &s);
 485 
 486 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
 487   s.main.c_oflag |= OPOST;      /* Enable output postprocessing */
 488   s.main.c_oflag &= ~ONLCR;     /* Disable map of NL to CR-NL on output */
 489 #ifdef NLDLY
 490   /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html
 491      Some versions of GNU Hurd do not have FFDLY?  */
 492 #ifdef FFDLY
 493   s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
 494                                 /* No output delays */
 495 #else
 496   s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
 497                                 /* No output delays */
 498 #endif
 499 #endif
 500   s.main.c_lflag &= ~ECHO;      /* Disable echo */
 501   s.main.c_lflag |= ISIG;       /* Enable signals */
 502 #ifdef IUCLC
 503   s.main.c_iflag &= ~IUCLC;     /* Disable downcasing on input.  */
 504 #endif
 505 #ifdef ISTRIP
 506   s.main.c_iflag &= ~ISTRIP;    /* don't strip 8th bit on input */
 507 #endif
 508 #ifdef OLCUC
 509   s.main.c_oflag &= ~OLCUC;     /* Disable upcasing on output.  */
 510 #endif
 511   s.main.c_oflag &= ~TAB3;      /* Disable tab expansion */
 512   s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
 513   s.main.c_cc[VERASE] = CDISABLE;       /* disable erase processing */
 514   s.main.c_cc[VKILL] = CDISABLE;        /* disable kill processing */
 515 
 516 #ifdef HPUX
 517   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 518 #endif /* HPUX */
 519 
 520 #ifdef SIGNALS_VIA_CHARACTERS
 521   /* the QUIT and INTR character are used in process_send_signal
 522      so set them here to something useful.  */
 523   if (s.main.c_cc[VQUIT] == CDISABLE)
 524     s.main.c_cc[VQUIT] = '\\'&037;      /* Control-\ */
 525   if (s.main.c_cc[VINTR] == CDISABLE)
 526     s.main.c_cc[VINTR] = 'C'&037;       /* Control-C */
 527 #endif /* not SIGNALS_VIA_CHARACTERS */
 528 
 529 #ifdef AIX
 530   /* Also, PTY overloads NUL and BREAK.
 531      don't ignore break, but don't signal either, so it looks like NUL.  */
 532   s.main.c_iflag &= ~IGNBRK;
 533   s.main.c_iflag &= ~BRKINT;
 534   /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
 535      unconditionally.  Then a SIGNALS_VIA_CHARACTERS conditional
 536      would force it to 0377.  That looks like duplicated code.  */
 537   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 538 #endif /* AIX */
 539 
 540 #else /* not HAVE_TERMIO */
 541 
 542   s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
 543                        | CBREAK | TANDEM);
 544   s.main.sg_flags |= LPASS8;
 545   s.main.sg_erase = 0377;
 546   s.main.sg_kill = 0377;
 547   s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */
 548 
 549   /* We used to enable ICANON (and set VEOF to 04), but this leads to
 550      problems where process.c wants to send EOFs every once in a while
 551      to force the output, which leads to weird effects when the
 552      subprocess has disabled ICANON and ends up seeing those spurious
 553      extra EOFs.  So we don't send EOFs any more in
 554      process.c:send_process, and instead we disable ICANON by default,
 555      so if a subsprocess sets up ICANON, it's his problem (or the Elisp
 556      package that talks to it) to deal with lines that are too long.  */
 557   s.main.c_lflag &= ~ICANON;    /* Disable line editing and eof processing */
 558   s.main.c_cc[VMIN] = 1;
 559   s.main.c_cc[VTIME] = 0;
 560 
 561 #endif /* not HAVE_TERMIO */
 562 
 563   EMACS_SET_TTY (out, &s, 0);
 564 
 565 #endif /* not DOS_NT */
 566 }
 567 
 568 #endif /* subprocesses */
 569 
 570 /* Record a signal code and the handler for it.  */
 571 struct save_signal
 572 {
 573   int code;
 574   SIGTYPE (*handler) P_ ((int));
 575 };
 576 
 577 static void save_signal_handlers P_ ((struct save_signal *));
 578 static void restore_signal_handlers P_ ((struct save_signal *));
 579 
 580 /* Suspend the Emacs process; give terminal to its superior.  */
 581 
 582 void
 583 sys_suspend ()
 584 {
 585 #if defined (SIGTSTP) && !defined (MSDOS)
 586 
 587   {
 588     int pgrp = EMACS_GETPGRP (0);
 589     EMACS_KILLPG (pgrp, SIGTSTP);
 590   }
 591 
 592 #else /* No SIGTSTP */
 593 /* On a system where suspending is not implemented,
 594    instead fork a subshell and let it talk directly to the terminal
 595    while we wait.  */
 596   sys_subshell ();
 597 
 598 #endif /* no SIGTSTP */
 599 }
 600 
 601 /* Fork a subshell.  */
 602 
 603 void
 604 sys_subshell ()
 605 {
 606 #ifdef DOS_NT   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
 607   int st;
 608   char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
 609 #endif
 610   int pid;
 611   struct save_signal saved_handlers[5];
 612   Lisp_Object dir;
 613   unsigned char *str = 0;
 614   int len;
 615 
 616   saved_handlers[0].code = SIGINT;
 617   saved_handlers[1].code = SIGQUIT;
 618   saved_handlers[2].code = SIGTERM;
 619 #ifdef SIGIO
 620   saved_handlers[3].code = SIGIO;
 621   saved_handlers[4].code = 0;
 622 #else
 623   saved_handlers[3].code = 0;
 624 #endif
 625 
 626   /* Mentioning current_buffer->buffer would mean including buffer.h,
 627      which somehow wedges the hp compiler.  So instead...  */
 628 
 629   dir = intern ("default-directory");
 630   if (NILP (Fboundp (dir)))
 631     goto xyzzy;
 632   dir = Fsymbol_value (dir);
 633   if (!STRINGP (dir))
 634     goto xyzzy;
 635 
 636   dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
 637   str = (unsigned char *) alloca (SCHARS (dir) + 2);
 638   len = SCHARS (dir);
 639   bcopy (SDATA (dir), str, len);
 640   if (str[len - 1] != '/') str[len++] = '/';
 641   str[len] = 0;
 642  xyzzy:
 643 
 644 #ifdef DOS_NT
 645   pid = 0;
 646   save_signal_handlers (saved_handlers);
 647   synch_process_alive = 1;
 648 #else
 649   pid = vfork ();
 650   if (pid == -1)
 651     error ("Can't spawn subshell");
 652 #endif
 653 
 654   if (pid == 0)
 655     {
 656       char *sh = 0;
 657 
 658 #ifdef DOS_NT    /* MW, Aug 1993 */
 659       getwd (oldwd);
 660       if (sh == 0)
 661         sh = (char *) egetenv ("SUSPEND");      /* KFS, 1994-12-14 */
 662 #endif
 663       if (sh == 0)
 664         sh = (char *) egetenv ("SHELL");
 665       if (sh == 0)
 666         sh = "sh";
 667 
 668       /* Use our buffer's default directory for the subshell.  */
 669       if (str)
 670         chdir ((char *) str);
 671 
 672 #ifdef subprocesses
 673       close_process_descs ();   /* Close Emacs's pipes/ptys */
 674 #endif
 675 
 676 #ifdef SET_EMACS_PRIORITY
 677       {
 678         extern EMACS_INT emacs_priority;
 679 
 680         if (emacs_priority < 0)
 681           nice (-emacs_priority);
 682       }
 683 #endif
 684 
 685 #ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
 686       {
 687         char *epwd = getenv ("PWD");
 688         char old_pwd[MAXPATHLEN+1+4];
 689 
 690         /* If PWD is set, pass it with corrected value.  */
 691         if (epwd)
 692           {
 693             strcpy (old_pwd, epwd);
 694             if (str[len - 1] == '/')
 695               str[len - 1] = '\0';
 696             setenv ("PWD", str, 1);
 697           }
 698         st = system (sh);
 699         chdir (oldwd);
 700         if (epwd)
 701           putenv (old_pwd);     /* restore previous value */
 702       }
 703 #else /* not MSDOS */
 704 #ifdef  WINDOWSNT
 705       /* Waits for process completion */
 706       pid = _spawnlp (_P_WAIT, sh, sh, NULL);
 707       chdir (oldwd);
 708       if (pid == -1)
 709         write (1, "Can't execute subshell", 22);
 710 #else   /* not WINDOWSNT */
 711       execlp (sh, sh, (char *) 0);
 712       write (1, "Can't execute subshell", 22);
 713       _exit (1);
 714 #endif  /* not WINDOWSNT */
 715 #endif /* not MSDOS */
 716     }
 717 
 718   /* Do this now if we did not do it before.  */
 719 #ifndef MSDOS
 720   save_signal_handlers (saved_handlers);
 721   synch_process_alive = 1;
 722 #endif
 723 
 724 #ifndef DOS_NT
 725   wait_for_termination (pid);
 726 #endif
 727   restore_signal_handlers (saved_handlers);
 728   synch_process_alive = 0;
 729 }
 730 
 731 static void
 732 save_signal_handlers (saved_handlers)
 733      struct save_signal *saved_handlers;
 734 {
 735   while (saved_handlers->code)
 736     {
 737       saved_handlers->handler
 738         = (SIGTYPE (*) P_ ((int))) signal (saved_handlers->code, SIG_IGN);
 739       saved_handlers++;
 740     }
 741 }
 742 
 743 static void
 744 restore_signal_handlers (saved_handlers)
 745      struct save_signal *saved_handlers;
 746 {
 747   while (saved_handlers->code)
 748     {
 749       signal (saved_handlers->code, saved_handlers->handler);
 750       saved_handlers++;
 751     }
 752 }
 753 
 754 #ifndef SIGIO
 755 /* If SIGIO is broken, don't do anything. */
 756 void
 757 init_sigio (int fd)
 758 {
 759 }
 760 
 761 void
 762 reset_sigio (int fd)
 763 {
 764 }
 765 
 766 void
 767 request_sigio (void)
 768 {
 769 }
 770 
 771 void
 772 unrequest_sigio (void)
 773 {
 774 }
 775 
 776 #else
 777 #ifdef F_SETFL
 778 
 779 int old_fcntl_flags[MAXDESC];
 780 
 781 void
 782 init_sigio (fd)
 783      int fd;
 784 {
 785 #ifdef FASYNC
 786   old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
 787   fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
 788 #endif
 789   interrupts_deferred = 0;
 790 }
 791 
 792 void
 793 reset_sigio (fd)
 794      int fd;
 795 {
 796 #ifdef FASYNC
 797   fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
 798 #endif
 799 }
 800 
 801 #ifdef FASYNC           /* F_SETFL does not imply existence of FASYNC */
 802 /* XXX Uhm, FASYNC is not used anymore here. */
 803 /* XXX Yeah, but you need it for SIGIO, don't you? */
 804 
 805 void
 806 request_sigio ()
 807 {
 808   if (noninteractive)
 809     return;
 810 
 811 #ifdef SIGWINCH
 812   sigunblock (sigmask (SIGWINCH));
 813 #endif
 814   sigunblock (sigmask (SIGIO));
 815 
 816   interrupts_deferred = 0;
 817 }
 818 
 819 void
 820 unrequest_sigio (void)
 821 { 
 822   if (noninteractive)
 823     return;
 824 
 825 #if 0 /* XXX What's wrong with blocking SIGIO under X?  */
 826   if (x_display_list)
 827     return;
 828 #endif
 829 
 830 #ifdef SIGWINCH
 831   sigblock (sigmask (SIGWINCH));
 832 #endif
 833   sigblock (sigmask (SIGIO));
 834   interrupts_deferred = 1;
 835 }
 836 
 837 #else /* no FASYNC */
 838 #ifndef MSDOS
 839 
 840 void
 841 request_sigio ()
 842 {
 843   if (noninteractive || read_socket_hook)
 844     return;
 845 
 846   croak ("request_sigio");
 847 }
 848 
 849 void
 850 unrequest_sigio ()
 851 {
 852   if (noninteractive || read_socket_hook)
 853     return;
 854 
 855   croak ("unrequest_sigio");
 856 }
 857 
 858 #endif /* MSDOS */
 859 #endif /* FASYNC */
 860 #endif /* F_SETFL */
 861 #endif /* SIGIO */
 862 
 863 
 864 /* Getting and setting emacs_tty structures.  */
 865 
 866 /* Set *TC to the parameters associated with the terminal FD.
 867    Return zero if all's well, or -1 if we ran into an error we
 868    couldn't deal with.  */
 869 int
 870 emacs_get_tty (fd, settings)
 871      int fd;
 872      struct emacs_tty *settings;
 873 {
 874   /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
 875 #ifdef HAVE_TCATTR
 876   /* We have those nifty POSIX tcmumbleattr functions.  */
 877   bzero (&settings->main, sizeof (settings->main));
 878   if (tcgetattr (fd, &settings->main) < 0)
 879     return -1;
 880 
 881 #else
 882 #ifdef HAVE_TERMIO
 883   /* The SYSV-style interface?  */
 884   if (ioctl (fd, TCGETA, &settings->main) < 0)
 885     return -1;
 886 
 887 #else
 888 #ifndef DOS_NT
 889   /* I give up - I hope you have the BSD ioctls.  */
 890   if (ioctl (fd, TIOCGETP, &settings->main) < 0)
 891     return -1;
 892 #endif /* not DOS_NT */
 893 #endif
 894 #endif
 895 
 896   /* Suivant - Do we have to get struct ltchars data?  */
 897 #ifdef HAVE_LTCHARS
 898   if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
 899     return -1;
 900 #endif
 901 
 902   /* How about a struct tchars and a wordful of lmode bits?  */
 903 #ifdef HAVE_TCHARS
 904   if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
 905       || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
 906     return -1;
 907 #endif
 908 
 909   /* We have survived the tempest.  */
 910   return 0;
 911 }
 912 
 913 
 914 /* Set the parameters of the tty on FD according to the contents of
 915    *SETTINGS.  If FLUSHP is non-zero, we discard input.
 916    Return 0 if all went well, and -1 if anything failed.  */
 917 
 918 int
 919 emacs_set_tty (fd, settings, flushp)
 920      int fd;
 921      struct emacs_tty *settings;
 922      int flushp;
 923 {
 924   /* Set the primary parameters - baud rate, character size, etcetera.  */
 925 #ifdef HAVE_TCATTR
 926   int i;
 927   /* We have those nifty POSIX tcmumbleattr functions.
 928      William J. Smith <wjs@wiis.wang.com> writes:
 929      "POSIX 1003.1 defines tcsetattr to return success if it was
 930      able to perform any of the requested actions, even if some
 931      of the requested actions could not be performed.
 932      We must read settings back to ensure tty setup properly.
 933      AIX requires this to keep tty from hanging occasionally."  */
 934   /* This make sure that we don't loop indefinitely in here.  */
 935   for (i = 0 ; i < 10 ; i++)
 936     if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
 937       {
 938         if (errno == EINTR)
 939           continue;
 940         else
 941           return -1;
 942       }
 943     else
 944       {
 945         struct termios new;
 946 
 947         bzero (&new, sizeof (new));
 948         /* Get the current settings, and see if they're what we asked for.  */
 949         tcgetattr (fd, &new);
 950         /* We cannot use memcmp on the whole structure here because under
 951          * aix386 the termios structure has some reserved field that may
 952          * not be filled in.
 953          */
 954         if (   new.c_iflag == settings->main.c_iflag
 955             && new.c_oflag == settings->main.c_oflag
 956             && new.c_cflag == settings->main.c_cflag
 957             && new.c_lflag == settings->main.c_lflag
 958             && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
 959           break;
 960         else
 961           continue;
 962       }
 963 
 964 #else
 965 #ifdef HAVE_TERMIO
 966   /* The SYSV-style interface?  */
 967   if (ioctl (fd, flushp ? TCSETAF : TCSETAW, &settings->main) < 0)
 968     return -1;
 969 
 970 #else
 971 #ifndef DOS_NT
 972   /* I give up - I hope you have the BSD ioctls.  */
 973   if (ioctl (fd, (flushp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
 974     return -1;
 975 #endif /* not DOS_NT */
 976 
 977 #endif
 978 #endif
 979 
 980   /* Suivant - Do we have to get struct ltchars data?  */
 981 #ifdef HAVE_LTCHARS
 982   if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
 983     return -1;
 984 #endif
 985 
 986   /* How about a struct tchars and a wordful of lmode bits?  */
 987 #ifdef HAVE_TCHARS
 988   if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
 989       || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
 990     return -1;
 991 #endif
 992 
 993   /* We have survived the tempest.  */
 994   return 0;
 995 }
 996 
 997 
 998 
 999 #ifdef F_SETOWN
1000 int old_fcntl_owner[MAXDESC];
1001 #endif /* F_SETOWN */
1002 
1003 /* This may also be defined in stdio,
1004    but if so, this does no harm,
1005    and using the same name avoids wasting the other one's space.  */
1006 
1007 #if defined (USG)
1008 unsigned char _sobuf[BUFSIZ+8];
1009 #else
1010 char _sobuf[BUFSIZ];
1011 #endif
1012 
1013 #ifdef HAVE_LTCHARS
1014 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
1015 #endif
1016 #ifdef HAVE_TCHARS
1017 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
1018 #endif
1019 
1020 /* Initialize the terminal mode on all tty devices that are currently
1021    open. */
1022 
1023 void
1024 init_all_sys_modes (void)
1025 {
1026   struct tty_display_info *tty;
1027   for (tty = tty_list; tty; tty = tty->next)
1028     init_sys_modes (tty);
1029 }
1030 
1031 /* Initialize the terminal mode on the given tty device. */
1032 
1033 void
1034 init_sys_modes (tty_out)
1035      struct tty_display_info *tty_out;
1036 {
1037   struct emacs_tty tty;
1038 
1039   Vtty_erase_char = Qnil;
1040 
1041   if (noninteractive)
1042     return;
1043 
1044   if (!tty_out->output)
1045     return;                     /* The tty is suspended. */
1046   
1047   if (! tty_out->old_tty)
1048     tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
1049       
1050   EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty);
1051 
1052   tty = *tty_out->old_tty;
1053 
1054 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
1055   XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
1056 
1057   tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
1058   tty.main.c_iflag &= ~ICRNL;   /* Disable map of CR to NL on input */
1059 #ifdef INLCR  /* I'm just being cautious,
1060                  since I can't check how widespread INLCR is--rms.  */
1061   tty.main.c_iflag &= ~INLCR;   /* Disable map of NL to CR on input */
1062 #endif
1063 #ifdef ISTRIP
1064   tty.main.c_iflag &= ~ISTRIP;  /* don't strip 8th bit on input */
1065 #endif
1066   tty.main.c_lflag &= ~ECHO;    /* Disable echo */
1067   tty.main.c_lflag &= ~ICANON;  /* Disable erase/kill processing */
1068 #ifdef IEXTEN
1069   tty.main.c_lflag &= ~IEXTEN;  /* Disable other editing characters.  */
1070 #endif
1071   tty.main.c_lflag |= ISIG;     /* Enable signals */
1072   if (tty_out->flow_control)
1073     {
1074       tty.main.c_iflag |= IXON; /* Enable start/stop output control */
1075 #ifdef IXANY
1076       tty.main.c_iflag &= ~IXANY;
1077 #endif /* IXANY */
1078     }
1079   else
1080     tty.main.c_iflag &= ~IXON;  /* Disable start/stop output control */
1081   tty.main.c_oflag &= ~ONLCR;   /* Disable map of NL to CR-NL
1082                                    on output */
1083   tty.main.c_oflag &= ~TAB3;    /* Disable tab expansion */
1084 #ifdef CS8
1085   if (tty_out->meta_key)
1086     {
1087       tty.main.c_cflag |= CS8;  /* allow 8th bit on input */
1088       tty.main.c_cflag &= ~PARENB;/* Don't check parity */
1089     }
1090 #endif
1091   if (tty_out->input == stdin)
1092     {
1093       tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
1094       /* Set up C-g for both SIGQUIT and SIGINT.
1095          We don't know which we will get, but we handle both alike
1096          so which one it really gives us does not matter.  */
1097       tty.main.c_cc[VQUIT] = quit_char;
1098     }
1099   else
1100     {
1101       /* We normally don't get interrupt or quit signals from tty
1102          devices other than our controlling terminal; therefore,
1103          we must handle C-g as normal input.  Unfortunately, this
1104          means that the interrupt and quit feature must be
1105          disabled on secondary ttys, or we would not even see the
1106          keypress.
1107          
1108          Note that even though emacsclient could have special code
1109          to pass SIGINT to Emacs, we should _not_ enable
1110          interrupt/quit keys for emacsclient frames.  This means
1111          that we can't break out of loops in C code from a
1112          secondary tty frame, but we can always decide what
1113          display the C-g came from, which is more important from a
1114          usability point of view.  (Consider the case when two
1115          people work together using the same Emacs instance.)  */
1116       tty.main.c_cc[VINTR] = CDISABLE;
1117       tty.main.c_cc[VQUIT] = CDISABLE;
1118     }
1119   tty.main.c_cc[VMIN] = 1;      /* Input should wait for at least 1 char */
1120   tty.main.c_cc[VTIME] = 0;     /* no matter how long that takes.  */
1121 #ifdef VSWTCH
1122   tty.main.c_cc[VSWTCH] = CDISABLE;     /* Turn off shell layering use
1123                                            of C-z */
1124 #endif /* VSWTCH */
1125   
1126 #if defined (__mips__) || defined (HAVE_TCATTR)
1127 #ifdef VSUSP
1128   tty.main.c_cc[VSUSP] = CDISABLE;      /* Turn off mips handling of C-z.  */
1129 #endif /* VSUSP */
1130 #ifdef V_DSUSP
1131   tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y.  */
1132 #endif /* V_DSUSP */
1133 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
1134   tty.main.c_cc[VDSUSP] = CDISABLE;
1135 #endif /* VDSUSP */
1136 #ifdef VLNEXT
1137   tty.main.c_cc[VLNEXT] = CDISABLE;
1138 #endif /* VLNEXT */
1139 #ifdef VREPRINT
1140   tty.main.c_cc[VREPRINT] = CDISABLE;
1141 #endif /* VREPRINT */
1142 #ifdef VWERASE
1143   tty.main.c_cc[VWERASE] = CDISABLE;
1144 #endif /* VWERASE */
1145 #ifdef VDISCARD
1146   tty.main.c_cc[VDISCARD] = CDISABLE;
1147 #endif /* VDISCARD */
1148 
1149   if (tty_out->flow_control)
1150     {
1151 #ifdef VSTART
1152       tty.main.c_cc[VSTART] = '\021';
1153 #endif /* VSTART */
1154 #ifdef VSTOP
1155       tty.main.c_cc[VSTOP] = '\023';
1156 #endif /* VSTOP */
1157     }
1158   else
1159     {
1160 #ifdef VSTART
1161       tty.main.c_cc[VSTART] = CDISABLE;
1162 #endif /* VSTART */
1163 #ifdef VSTOP
1164       tty.main.c_cc[VSTOP] = CDISABLE;
1165 #endif /* VSTOP */
1166     }
1167 #endif /* mips or HAVE_TCATTR */
1168 
1169 #ifdef AIX
1170   tty.main.c_cc[VSTRT] = CDISABLE;
1171   tty.main.c_cc[VSTOP] = CDISABLE;
1172   tty.main.c_cc[VSUSP] = CDISABLE;
1173   tty.main.c_cc[VDSUSP] = CDISABLE;
1174   if (tty_out->flow_control)
1175     {
1176 #ifdef VSTART
1177       tty.main.c_cc[VSTART] = '\021';
1178 #endif /* VSTART */
1179 #ifdef VSTOP
1180       tty.main.c_cc[VSTOP] = '\023';
1181 #endif /* VSTOP */
1182     }
1183   /* Also, PTY overloads NUL and BREAK.
1184      don't ignore break, but don't signal either, so it looks like NUL.
1185      This really serves a purpose only if running in an XTERM window
1186      or via TELNET or the like, but does no harm elsewhere.  */
1187   tty.main.c_iflag &= ~IGNBRK;
1188   tty.main.c_iflag &= ~BRKINT;
1189 #endif
1190 #else /* if not HAVE_TERMIO */
1191 #ifndef DOS_NT
1192   XSETINT (Vtty_erase_char, tty.main.sg_erase);
1193   tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
1194   if (meta_key)
1195     tty.main.sg_flags |= ANYP;
1196   tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
1197 #endif /* not DOS_NT */
1198 #endif /* not HAVE_TERMIO */
1199 
1200   /* If going to use CBREAK mode, we must request C-g to interrupt
1201      and turn off start and stop chars, etc.  If not going to use
1202      CBREAK mode, do this anyway so as to turn off local flow
1203      control for user coming over network on 4.2; in this case,
1204      only t_stopc and t_startc really matter.  */
1205 #ifndef HAVE_TERMIO
1206 #ifdef HAVE_TCHARS
1207   /* Note: if not using CBREAK mode, it makes no difference how we
1208      set this */
1209   tty.tchars = new_tchars;
1210   tty.tchars.t_intrc = quit_char;
1211   if (tty_out->flow_control)
1212     {
1213       tty.tchars.t_startc = '\021';
1214       tty.tchars.t_stopc = '\023';
1215     }
1216   
1217   tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode;
1218   
1219 #endif /* HAVE_TCHARS */
1220 #endif /* not HAVE_TERMIO */
1221 
1222 #ifdef HAVE_LTCHARS
1223   tty.ltchars = new_ltchars;
1224 #endif /* HAVE_LTCHARS */
1225 #ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
1226   if (!tty_out->term_initted)
1227     internal_terminal_init ();
1228   dos_ttraw (tty_out);
1229 #endif
1230 
1231   EMACS_SET_TTY (fileno (tty_out->input), &tty, 0);
1232 
1233   /* This code added to insure that, if flow-control is not to be used,
1234      we have an unlocked terminal at the start. */
1235 
1236 #ifdef TCXONC
1237   if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
1238 #endif
1239 #ifdef TIOCSTART
1240   if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
1241 #endif
1242 
1243 #if defined (HAVE_TERMIOS) || defined (HPUX)
1244 #ifdef TCOON
1245   if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
1246 #endif
1247 #endif
1248 
1249 #ifdef F_SETFL
1250 #ifdef F_GETOWN         /* F_SETFL does not imply existence of F_GETOWN */
1251   if (interrupt_input)
1252     {
1253       old_fcntl_owner[fileno (tty_out->input)] =
1254         fcntl (fileno (tty_out->input), F_GETOWN, 0);
1255       fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
1256       init_sigio (fileno (tty_out->input));
1257 #ifdef HAVE_GPM
1258       if (gpm_tty == tty_out)
1259         {
1260           /* Arrange for mouse events to give us SIGIO signals.  */
1261           fcntl (gpm_fd, F_SETOWN, getpid ());
1262           fcntl (gpm_fd, F_SETFL, fcntl (gpm_fd, F_GETFL, 0) | O_NONBLOCK);
1263           init_sigio (gpm_fd);
1264         }
1265 #endif /* HAVE_GPM */
1266     }
1267 #endif /* F_GETOWN */
1268 #endif /* F_SETFL */
1269 
1270 #ifdef _IOFBF
1271   /* This symbol is defined on recent USG systems.
1272      Someone says without this call USG won't really buffer the file
1273      even with a call to setbuf. */
1274   setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
1275 #else
1276   setbuf (tty_out->output, (char *) _sobuf);
1277 #endif
1278 
1279   if (tty_out->terminal->set_terminal_modes_hook)
1280     tty_out->terminal->set_terminal_modes_hook (tty_out->terminal);
1281 
1282   if (!tty_out->term_initted)
1283     {
1284       Lisp_Object tail, frame;
1285       FOR_EACH_FRAME (tail, frame)
1286         {
1287           /* XXX This needs to be revised. */
1288           if (FRAME_TERMCAP_P (XFRAME (frame))
1289               && FRAME_TTY (XFRAME (frame)) == tty_out)
1290             init_frame_faces (XFRAME (frame));
1291         }
1292     }
1293 
1294   if (tty_out->term_initted && no_redraw_on_reenter)
1295     {
1296       /* We used to call "direct_output_forward_char(0)" here,
1297          but it's not clear why, since it may not do anything anyway.  */
1298     }
1299   else
1300     {
1301       Lisp_Object tail, frame;
1302       frame_garbaged = 1;
1303       FOR_EACH_FRAME (tail, frame)
1304         {
1305           if ((FRAME_TERMCAP_P (XFRAME (frame))
1306                || FRAME_MSDOS_P (XFRAME (frame)))
1307               && FRAME_TTY (XFRAME (frame)) == tty_out)
1308             FRAME_GARBAGED_P (XFRAME (frame)) = 1;
1309         }
1310     }
1311 
1312   tty_out->term_initted = 1;
1313 }
1314 
1315 /* Return nonzero if safe to use tabs in output.
1316    At the time this is called, init_sys_modes has not been done yet.  */
1317 
1318 int
1319 tabs_safe_p (int fd)
1320 {
1321   struct emacs_tty etty;
1322 
1323   EMACS_GET_TTY (fd, &etty);
1324   return EMACS_TTY_TABS_OK (&etty);
1325 }
1326 
1327 /* Get terminal size from system.
1328    Store number of lines into *HEIGHTP and width into *WIDTHP.
1329    We store 0 if there's no valid information.  */
1330 
1331 void
1332 get_tty_size (int fd, int *widthp, int *heightp)
1333 {
1334 
1335 #ifdef TIOCGWINSZ
1336 
1337   /* BSD-style.  */
1338   struct winsize size;
1339 
1340   if (ioctl (fd, TIOCGWINSZ, &size) == -1)
1341     *widthp = *heightp = 0;
1342   else
1343     {
1344       *widthp = size.ws_col;
1345       *heightp = size.ws_row;
1346     }
1347 
1348 #else
1349 #ifdef TIOCGSIZE
1350 
1351   /* SunOS - style.  */
1352   struct ttysize size;
1353 
1354   if (ioctl (fd, TIOCGSIZE, &size) == -1)
1355     *widthp = *heightp = 0;
1356   else
1357     {
1358       *widthp = size.ts_cols;
1359       *heightp = size.ts_lines;
1360     }
1361 
1362 #else
1363 #ifdef MSDOS
1364   *widthp = ScreenCols ();
1365   *heightp = ScreenRows ();
1366 #else /* system doesn't know size */
1367   *widthp = 0;
1368   *heightp = 0;
1369 #endif
1370 #endif /* not SunOS-style */
1371 #endif /* not BSD-style */
1372 }
1373 
1374 /* Set the logical window size associated with descriptor FD
1375    to HEIGHT and WIDTH.  This is used mainly with ptys.  */
1376 
1377 int
1378 set_window_size (fd, height, width)
1379      int fd, height, width;
1380 {
1381 #ifdef TIOCSWINSZ
1382 
1383   /* BSD-style.  */
1384   struct winsize size;
1385   size.ws_row = height;
1386   size.ws_col = width;
1387 
1388   if (ioctl (fd, TIOCSWINSZ, &size) == -1)
1389     return 0; /* error */
1390   else
1391     return 1;
1392 
1393 #else
1394 #ifdef TIOCSSIZE
1395 
1396   /* SunOS - style.  */
1397   struct ttysize size;
1398   size.ts_lines = height;
1399   size.ts_cols = width;
1400 
1401   if (ioctl (fd, TIOCGSIZE, &size) == -1)
1402     return 0;
1403   else
1404     return 1;
1405 #else
1406   return -1;
1407 #endif /* not SunOS-style */
1408 #endif /* not BSD-style */
1409 }
1410 
1411 
1412 
1413 /* Prepare all terminal devices for exiting Emacs. */
1414 
1415 void
1416 reset_all_sys_modes (void)
1417 {
1418   struct tty_display_info *tty;
1419   for (tty = tty_list; tty; tty = tty->next)
1420     reset_sys_modes (tty);
1421 }
1422 
1423 /* Prepare the terminal for closing it; move the cursor to the
1424    bottom of the frame, turn off interrupt-driven I/O, etc.  */
1425 
1426 void
1427 reset_sys_modes (tty_out)
1428      struct tty_display_info *tty_out;
1429 {
1430   if (noninteractive)
1431     {
1432       fflush (stdout);
1433       return;
1434     }
1435   if (!tty_out->term_initted)
1436     return;
1437 
1438   if (!tty_out->output)
1439     return;                     /* The tty is suspended. */
1440   
1441   /* Go to and clear the last line of the terminal. */
1442 
1443   cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1444   
1445   /* Code adapted from tty_clear_end_of_line. */
1446   if (tty_out->TS_clr_line)
1447     {
1448       emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
1449     }
1450   else
1451     {                   /* have to do it the hard way */
1452       int i;
1453       tty_turn_off_insert (tty_out);
1454       
1455       for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
1456         {
1457           fputc (' ', tty_out->output);
1458         }
1459     }
1460   
1461   cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1462   fflush (tty_out->output);
1463   
1464   if (tty_out->terminal->reset_terminal_modes_hook)
1465     tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
1466 
1467 #ifdef BSD_SYSTEM
1468   /* Avoid possible loss of output when changing terminal modes.  */
1469   fsync (fileno (tty_out->output));
1470 #endif
1471 
1472 #ifdef F_SETFL
1473 #ifdef F_SETOWN         /* F_SETFL does not imply existence of F_SETOWN */
1474   if (interrupt_input)
1475     {
1476       reset_sigio (fileno (tty_out->input));
1477       fcntl (fileno (tty_out->input), F_SETOWN,
1478              old_fcntl_owner[fileno (tty_out->input)]);
1479     }
1480 #endif /* F_SETOWN */
1481 #ifdef O_NDELAY
1482   fcntl (fileno (tty_out->input), F_SETFL,
1483          fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
1484 #endif
1485 #endif /* F_SETFL */
1486 
1487   if (tty_out->old_tty)
1488     while (EMACS_SET_TTY (fileno (tty_out->input),
1489                           tty_out->old_tty, 0) < 0 && errno == EINTR)
1490       ;
1491 
1492 #ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
1493   dos_ttcooked ();
1494 #endif
1495 
1496 }
1497 
1498 #ifdef HAVE_PTYS
1499 
1500 /* Set up the proper status flags for use of a pty.  */
1501 
1502 void
1503 setup_pty (fd)
1504      int fd;
1505 {
1506   /* I'm told that TOICREMOTE does not mean control chars
1507      "can't be sent" but rather that they don't have
1508      input-editing or signaling effects.
1509      That should be good, because we have other ways
1510      to do those things in Emacs.
1511      However, telnet mode seems not to work on 4.2.
1512      So TIOCREMOTE is turned off now. */
1513 
1514   /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1515      will hang.  In particular, the "timeout" feature (which
1516      causes a read to return if there is no data available)
1517      does this.  Also it is known that telnet mode will hang
1518      in such a way that Emacs must be stopped (perhaps this
1519      is the same problem).
1520 
1521      If TIOCREMOTE is turned off, then there is a bug in
1522      hp-ux which sometimes loses data.  Apparently the
1523      code which blocks the master process when the internal
1524      buffer fills up does not work.  Other than this,
1525      though, everything else seems to work fine.
1526 
1527      Since the latter lossage is more benign, we may as well
1528      lose that way.  -- cph */
1529 #ifdef FIONBIO
1530 #if defined(UNIX98_PTYS)
1531   {
1532     int on = 1;
1533     ioctl (fd, FIONBIO, &on);
1534   }
1535 #endif
1536 #endif
1537 }
1538 #endif /* HAVE_PTYS */
1539 
1540 #if !defined(CANNOT_DUMP) || !defined(SYSTEM_MALLOC)
1541 /* Some systems that cannot dump also cannot implement these.  */
1542 
1543 /*
1544  *      Return the address of the start of the text segment prior to
1545  *      doing an unexec.  After unexec the return value is undefined.
1546  *      See crt0.c for further explanation and _start.
1547  *
1548  */
1549 
1550 #if !(defined (__NetBSD__) && defined (__ELF__))
1551 #ifndef HAVE_TEXT_START
1552 char *
1553 start_of_text ()
1554 {
1555 #ifdef TEXT_START
1556   return ((char *) TEXT_START);
1557 #else
1558   extern int _start ();
1559   return ((char *) _start);
1560 #endif /* TEXT_START */
1561 }
1562 #endif /* not HAVE_TEXT_START */
1563 #endif
1564 
1565 /*
1566  *      Return the address of the start of the data segment prior to
1567  *      doing an unexec.  After unexec the return value is undefined.
1568  *      See crt0.c for further information and definition of data_start.
1569  *
1570  *      Apparently, on BSD systems this is etext at startup.  On
1571  *      USG systems (swapping) this is highly mmu dependent and
1572  *      is also dependent on whether or not the program is running
1573  *      with shared text.  Generally there is a (possibly large)
1574  *      gap between end of text and start of data with shared text.
1575  *
1576  *      On Uniplus+ systems with shared text, data starts at a
1577  *      fixed address.  Each port (from a given oem) is generally
1578  *      different, and the specific value of the start of data can
1579  *      be obtained via the UniPlus+ specific "uvar" system call,
1580  *      however the method outlined in crt0.c seems to be more portable.
1581  *
1582  *      Probably what will have to happen when a USG unexec is available,
1583  *      at least on UniPlus, is temacs will have to be made unshared so
1584  *      that text and data are contiguous.  Then once loadup is complete,
1585  *      unexec will produce a shared executable where the data can be
1586  *      at the normal shared text boundary and the startofdata variable
1587  *      will be patched by unexec to the correct value.
1588  *
1589  */
1590 
1591 #ifndef start_of_data
1592 char *
1593 start_of_data ()
1594 {
1595 #ifdef DATA_START
1596   return ((char *) DATA_START);
1597 #else
1598 #ifdef ORDINARY_LINK
1599   /*
1600    * This is a hack.  Since we're not linking crt0.c or pre_crt0.c,
1601    * data_start isn't defined.  We take the address of environ, which
1602    * is known to live at or near the start of the system crt0.c, and
1603    * we don't sweat the handful of bytes that might lose.
1604    */
1605   extern char **environ;
1606 
1607   return ((char *) &environ);
1608 #else
1609   extern int data_start;
1610   return ((char *) &data_start);
1611 #endif /* ORDINARY_LINK */
1612 #endif /* DATA_START */
1613 }
1614 #endif /* start_of_data */
1615 #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1616 
1617 /* init_system_name sets up the string for the Lisp function
1618    system-name to return. */
1619 
1620 extern Lisp_Object Vsystem_name;
1621 
1622 #ifdef HAVE_SOCKETS
1623 #include <sys/socket.h>
1624 #include <netdb.h>
1625 #endif /* HAVE_SOCKETS */
1626 
1627 #ifdef TRY_AGAIN
1628 #ifndef HAVE_H_ERRNO
1629 extern int h_errno;
1630 #endif
1631 #endif /* TRY_AGAIN */
1632 
1633 void
1634 init_system_name ()
1635 {
1636 #ifndef HAVE_GETHOSTNAME
1637   struct utsname uts;
1638   uname (&uts);
1639   Vsystem_name = build_string (uts.nodename);
1640 #else /* HAVE_GETHOSTNAME */
1641   unsigned int hostname_size = 256;
1642   char *hostname = (char *) alloca (hostname_size);
1643 
1644   /* Try to get the host name; if the buffer is too short, try
1645      again.  Apparently, the only indication gethostname gives of
1646      whether the buffer was large enough is the presence or absence
1647      of a '\0' in the string.  Eech.  */
1648   for (;;)
1649     {
1650       gethostname (hostname, hostname_size - 1);
1651       hostname[hostname_size - 1] = '\0';
1652 
1653       /* Was the buffer large enough for the '\0'?  */
1654       if (strlen (hostname) < hostname_size - 1)
1655         break;
1656 
1657       hostname_size <<= 1;
1658       hostname = (char *) alloca (hostname_size);
1659     }
1660 #ifdef HAVE_SOCKETS
1661   /* Turn the hostname into the official, fully-qualified hostname.
1662      Don't do this if we're going to dump; this can confuse system
1663      libraries on some machines and make the dumped emacs core dump. */
1664 #ifndef CANNOT_DUMP
1665   if (initialized)
1666 #endif /* not CANNOT_DUMP */
1667     if (! index (hostname, '.'))
1668       {
1669         int count;
1670 #ifdef HAVE_GETADDRINFO
1671         struct addrinfo *res;
1672         struct addrinfo hints;
1673         int ret;
1674 
1675         memset (&hints, 0, sizeof(hints));
1676         hints.ai_socktype = SOCK_STREAM;
1677         hints.ai_flags = AI_CANONNAME;
1678 
1679         for (count = 0;; count++)
1680           {
1681             if ((ret = getaddrinfo (hostname, NULL, &hints, &res)) == 0
1682                 || ret != EAI_AGAIN)
1683               break;
1684 
1685             if (count >= 5)
1686               break;
1687             Fsleep_for (make_number (1), Qnil);
1688           }
1689 
1690         if (ret == 0)
1691           {
1692             struct addrinfo *it = res;
1693             while (it)
1694               {
1695                 char *fqdn = it->ai_canonname;
1696                 if (fqdn && index (fqdn, '.')
1697                     && strcmp (fqdn, "localhost.localdomain") != 0)
1698                   break;
1699                 it = it->ai_next;
1700               }
1701             if (it)
1702               {
1703                 hostname = alloca (strlen (it->ai_canonname) + 1);
1704                 strcpy (hostname, it->ai_canonname);
1705               }
1706             freeaddrinfo (res);
1707           }
1708 #else /* !HAVE_GETADDRINFO */
1709         struct hostent *hp;
1710         for (count = 0;; count++)
1711           {
1712 
1713 #ifdef TRY_AGAIN
1714             h_errno = 0;
1715 #endif
1716             hp = gethostbyname (hostname);
1717 #ifdef TRY_AGAIN
1718             if (! (hp == 0 && h_errno == TRY_AGAIN))
1719 #endif
1720 
1721               break;
1722 
1723             if (count >= 5)
1724               break;
1725             Fsleep_for (make_number (1), Qnil);
1726           }
1727 
1728         if (hp)
1729           {
1730             char *fqdn = (char *) hp->h_name;
1731 
1732             if (!index (fqdn, '.'))
1733               {
1734                 /* We still don't have a fully qualified domain name.
1735                    Try to find one in the list of alternate names */
1736                 char **alias = hp->h_aliases;
1737                 while (*alias
1738                        && (!index (*alias, '.')
1739                            || !strcmp (*alias, "localhost.localdomain")))
1740                   alias++;
1741                 if (*alias)
1742                   fqdn = *alias;
1743               }
1744             hostname = fqdn;
1745           }
1746 #endif /* !HAVE_GETADDRINFO */
1747       }
1748 #endif /* HAVE_SOCKETS */
1749   Vsystem_name = build_string (hostname);
1750 #endif /* HAVE_GETHOSTNAME */
1751   {
1752     unsigned char *p;
1753     for (p = SDATA (Vsystem_name); *p; p++)
1754       if (*p == ' ' || *p == '\t')
1755         *p = '-';
1756   }
1757 }
1758 
1759 #ifndef MSDOS
1760 #if !defined (HAVE_SELECT)
1761 
1762 #include "sysselect.h"
1763 #undef select
1764 
1765 #if defined (HAVE_X_WINDOWS) && !defined (HAVE_SELECT)
1766 /* Cause explanatory error message at compile time,
1767    since the select emulation is not good enough for X.  */
1768 int *x = &x_windows_lose_if_no_select_system_call;
1769 #endif
1770 
1771 /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1772  * Only checks read descriptors.
1773  */
1774 /* How long to wait between checking fds in select */
1775 #define SELECT_PAUSE 1
1776 int select_alarmed;
1777 
1778 /* For longjmp'ing back to read_input_waiting.  */
1779 
1780 jmp_buf read_alarm_throw;
1781 
1782 /* Nonzero if the alarm signal should throw back to read_input_waiting.
1783    The read_socket_hook function sets this to 1 while it is waiting.  */
1784 
1785 int read_alarm_should_throw;
1786 
1787 SIGTYPE
1788 select_alarm ()
1789 {
1790   select_alarmed = 1;
1791   signal (SIGALRM, SIG_IGN);
1792   SIGNAL_THREAD_CHECK (SIGALRM);
1793   if (read_alarm_should_throw)
1794     longjmp (read_alarm_throw, 1);
1795 }
1796 
1797 #ifndef WINDOWSNT
1798 /* Only rfds are checked.  */
1799 int
1800 sys_select (nfds, rfds, wfds, efds, timeout)
1801      int nfds;
1802      SELECT_TYPE *rfds, *wfds, *efds;
1803      EMACS_TIME *timeout;
1804 {
1805   /* XXX This needs to be updated for multi-tty support.  Is there
1806      anybody who needs to emulate select these days?  */ 
1807  int ravail = 0;
1808   SELECT_TYPE orfds;
1809   int timeoutval;
1810   int *local_timeout;
1811   extern int proc_buffered_char[];
1812 #ifndef subprocesses
1813   int process_tick = 0, update_tick = 0;
1814 #else
1815   extern int process_tick, update_tick;
1816 #endif
1817   unsigned char buf;
1818 
1819 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
1820   /* If we're using X, then the native select will work; we only need the
1821      emulation for non-X usage.  */
1822   if (!NILP (Vinitial_window_system))
1823     return select (nfds, rfds, wfds, efds, timeout);
1824 #endif
1825   timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
1826   local_timeout = &timeoutval;
1827   FD_ZERO (&orfds);
1828   if (rfds)
1829     {
1830       orfds = *rfds;
1831       FD_ZERO (rfds);
1832     }
1833   if (wfds)
1834     FD_ZERO (wfds);
1835   if (efds)
1836     FD_ZERO (efds);
1837 
1838   /* If we are looking only for the terminal, with no timeout,
1839      just read it and wait -- that's more efficient.  */
1840   if (*local_timeout == 100000 && process_tick == update_tick
1841       && FD_ISSET (0, &orfds))
1842     {
1843       int fd;
1844       for (fd = 1; fd < nfds; ++fd)
1845         if (FD_ISSET (fd, &orfds))
1846           goto hardway;
1847       if (! detect_input_pending ())
1848         read_input_waiting ();
1849       FD_SET (0, rfds);
1850       return 1;
1851     }
1852 
1853  hardway:
1854   /* Once a second, till the timer expires, check all the flagged read
1855    * descriptors to see if any input is available.  If there is some then
1856    * set the corresponding bit in the return copy of rfds.
1857    */
1858   while (1)
1859     {
1860       register int to_check, fd;
1861 
1862       if (rfds)
1863         {
1864           for (to_check = nfds, fd = 0; --to_check >= 0; fd++)
1865             {
1866               if (FD_ISSET (fd, &orfds))
1867                 {
1868                   int avail = 0, status = 0;
1869 
1870                   if (fd == 0)
1871                     avail = detect_input_pending (); /* Special keyboard handler */
1872                   else
1873                     {
1874 #ifdef FIONREAD
1875                       status = ioctl (fd, FIONREAD, &avail);
1876 #else /* no FIONREAD */
1877                       /* Hoping it will return -1 if nothing available
1878                          or 0 if all 0 chars requested are read.  */
1879                       if (proc_buffered_char[fd] >= 0)
1880                         avail = 1;
1881                       else
1882                         {
1883                           avail = read (fd, &buf, 1);
1884                           if (avail > 0)
1885                             proc_buffered_char[fd] = buf;
1886                         }
1887 #endif /* no FIONREAD */
1888                     }
1889                   if (status >= 0 && avail > 0)
1890                     {
1891                       FD_SET (fd, rfds);
1892                       ravail++;
1893                     }
1894                 }
1895             }
1896         }
1897       if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
1898         break;
1899 
1900       turn_on_atimers (0);
1901       signal (SIGALRM, select_alarm);
1902       select_alarmed = 0;
1903       alarm (SELECT_PAUSE);
1904 
1905       /* Wait for a SIGALRM (or maybe a SIGTINT) */
1906       while (select_alarmed == 0 && *local_timeout != 0
1907              && process_tick == update_tick)
1908         {
1909           /* If we are interested in terminal input,
1910              wait by reading the terminal.
1911              That makes instant wakeup for terminal input at least.  */
1912           if (FD_ISSET (0, &orfds))
1913             {
1914               read_input_waiting ();
1915               if (detect_input_pending ())
1916                 select_alarmed = 1;
1917             }
1918           else
1919             pause ();
1920         }
1921       (*local_timeout) -= SELECT_PAUSE;
1922 
1923       /* Reset the old alarm if there was one.  */
1924       turn_on_atimers (1);
1925 
1926       if (*local_timeout == 0)  /* Stop on timer being cleared */
1927         break;
1928     }
1929   return ravail;
1930 }
1931 #endif /* not WINDOWSNT */
1932 
1933 /* Read keyboard input into the standard buffer,
1934    waiting for at least one character.  */
1935 
1936 void
1937 read_input_waiting ()
1938 {
1939   /* XXX This needs to be updated for multi-tty support.  Is there
1940      anybody who needs to emulate select these days?  */
1941   int nread, i;
1942   extern int quit_char;
1943 
1944   if (read_socket_hook)
1945     {
1946       struct input_event hold_quit;
1947 
1948       EVENT_INIT (hold_quit);
1949       hold_quit.kind = NO_EVENT;
1950 
1951       read_alarm_should_throw = 0;
1952       if (! setjmp (read_alarm_throw))
1953         nread = (*read_socket_hook) (0, 1, &hold_quit);
1954       else
1955         nread = -1;
1956 
1957       if (hold_quit.kind != NO_EVENT)
1958         kbd_buffer_store_event (&hold_quit);
1959     }
1960   else
1961     {
1962       struct input_event e;
1963       char buf[3];
1964       nread = read (fileno (stdin), buf, 1);
1965       EVENT_INIT (e);
1966 
1967       /* Scan the chars for C-g and store them in kbd_buffer.  */
1968       e.kind = ASCII_KEYSTROKE_EVENT;
1969       e.frame_or_window = selected_frame;
1970       e.modifiers = 0;
1971       for (i = 0; i < nread; i++)
1972         {
1973           /* Convert chars > 0177 to meta events if desired.
1974              We do this under the same conditions that read_avail_input does.  */
1975           if (read_socket_hook == 0)
1976             {
1977               /* If the user says she has a meta key, then believe her. */
1978               if (meta_key == 1 && (buf[i] & 0x80))
1979                 e.modifiers = meta_modifier;
1980               if (meta_key != 2)
1981                 buf[i] &= ~0x80;
1982             }
1983 
1984           XSETINT (e.code, buf[i]);
1985           kbd_buffer_store_event (&e);
1986           /* Don't look at input that follows a C-g too closely.
1987              This reduces lossage due to autorepeat on C-g.  */
1988           if (buf[i] == quit_char)
1989             break;
1990         }
1991     }
1992 }
1993 
1994 #if !defined (HAVE_SELECT)
1995 #define select sys_select
1996 #endif
1997 
1998 #endif /* not HAVE_SELECT */
1999 #endif /* not MSDOS */
2000 
2001 /* POSIX signals support - DJB */
2002 /* Anyone with POSIX signals should have ANSI C declarations */
2003 
2004 sigset_t empty_mask, full_mask;
2005 
2006 #ifndef WINDOWSNT
2007 
2008 signal_handler_t
2009 sys_signal (int signal_number, signal_handler_t action)
2010 {
2011   struct sigaction new_action, old_action;
2012   sigemptyset (&new_action.sa_mask);
2013   new_action.sa_handler = action;
2014   new_action.sa_flags = 0;
2015 #if defined (SA_RESTART)
2016   /* Emacs mostly works better with restartable system services. If this
2017      flag exists, we probably want to turn it on here.
2018      However, on some systems this resets the timeout of `select'
2019      which means that `select' never finishes if it keeps getting signals.
2020      BROKEN_SA_RESTART is defined on those systems.  */
2021   /* It's not clear why the comment above says "mostly works better".  --Stef
2022      When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
2023      for pending input so we need long-running syscalls to be interrupted
2024      after a signal that sets the interrupt_input_pending flag.  */
2025   /* Non-interactive keyboard input goes through stdio, where we always
2026      want restartable system calls.  */
2027 # if defined (BROKEN_SA_RESTART) || defined(SYNC_INPUT)
2028   if (noninteractive)
2029 # endif
2030     new_action.sa_flags = SA_RESTART;
2031 #endif
2032   sigaction (signal_number, &new_action, &old_action);
2033   return (old_action.sa_handler);
2034 }
2035 
2036 #endif  /* WINDOWSNT */
2037 
2038 #ifndef __GNUC__
2039 /* If we're compiling with GCC, we don't need this function, since it
2040    can be written as a macro.  */
2041 sigset_t
2042 sys_sigmask (int sig)
2043 {
2044   sigset_t mask;
2045   sigemptyset (&mask);
2046   sigaddset (&mask, sig);
2047   return mask;
2048 }
2049 #endif
2050 
2051 /* I'd like to have these guys return pointers to the mask storage in here,
2052    but there'd be trouble if the code was saving multiple masks.  I'll be
2053    safe and pass the structure.  It normally won't be more than 2 bytes
2054    anyhow. - DJB */
2055 
2056 sigset_t
2057 sys_sigblock (sigset_t new_mask)
2058 {
2059   sigset_t old_mask;
2060   sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
2061   return (old_mask);
2062 }
2063 
2064 sigset_t
2065 sys_sigunblock (sigset_t new_mask)
2066 {
2067   sigset_t old_mask;
2068   sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
2069   return (old_mask);
2070 }
2071 
2072 sigset_t
2073 sys_sigsetmask (sigset_t new_mask)
2074 {
2075   sigset_t old_mask;
2076   sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
2077   return (old_mask);
2078 }
2079 
2080 
2081 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
2082 static char *my_sys_siglist[NSIG];
2083 # ifdef sys_siglist
2084 #  undef sys_siglist
2085 # endif
2086 # define sys_siglist my_sys_siglist
2087 #endif
2088 
2089 void
2090 init_signals ()
2091 {
2092   sigemptyset (&empty_mask);
2093   sigfillset (&full_mask);
2094 
2095 #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
2096   if (! initialized)
2097     {
2098 # ifdef SIGABRT
2099       sys_siglist[SIGABRT] = "Aborted";
2100 # endif
2101 # ifdef SIGAIO
2102       sys_siglist[SIGAIO] = "LAN I/O interrupt";
2103 # endif
2104 # ifdef SIGALRM
2105       sys_siglist[SIGALRM] = "Alarm clock";
2106 # endif
2107 # ifdef SIGBUS
2108       sys_siglist[SIGBUS] = "Bus error";
2109 # endif
2110 # ifdef SIGCLD
2111       sys_siglist[SIGCLD] = "Child status changed";
2112 # endif
2113 # ifdef SIGCHLD
2114       sys_siglist[SIGCHLD] = "Child status changed";
2115 # endif
2116 # ifdef SIGCONT
2117       sys_siglist[SIGCONT] = "Continued";
2118 # endif
2119 # ifdef SIGDANGER
2120       sys_siglist[SIGDANGER] = "Swap space dangerously low";
2121 # endif
2122 # ifdef SIGDGNOTIFY
2123       sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
2124 # endif
2125 # ifdef SIGEMT
2126       sys_siglist[SIGEMT] = "Emulation trap";
2127 # endif
2128 # ifdef SIGFPE
2129       sys_siglist[SIGFPE] = "Arithmetic exception";
2130 # endif
2131 # ifdef SIGFREEZE
2132       sys_siglist[SIGFREEZE] = "SIGFREEZE";
2133 # endif
2134 # ifdef SIGGRANT
2135       sys_siglist[SIGGRANT] = "Monitor mode granted";
2136 # endif
2137 # ifdef SIGHUP
2138       sys_siglist[SIGHUP] = "Hangup";
2139 # endif
2140 # ifdef SIGILL
2141       sys_siglist[SIGILL] = "Illegal instruction";
2142 # endif
2143 # ifdef SIGINT
2144       sys_siglist[SIGINT] = "Interrupt";
2145 # endif
2146 # ifdef SIGIO
2147       sys_siglist[SIGIO] = "I/O possible";
2148 # endif
2149 # ifdef SIGIOINT
2150       sys_siglist[SIGIOINT] = "I/O intervention required";
2151 # endif
2152 # ifdef SIGIOT
2153       sys_siglist[SIGIOT] = "IOT trap";
2154 # endif
2155 # ifdef SIGKILL
2156       sys_siglist[SIGKILL] = "Killed";
2157 # endif
2158 # ifdef SIGLOST
2159       sys_siglist[SIGLOST] = "Resource lost";
2160 # endif
2161 # ifdef SIGLWP
2162       sys_siglist[SIGLWP] = "SIGLWP";
2163 # endif
2164 # ifdef SIGMSG
2165       sys_siglist[SIGMSG] = "Monitor mode data available";
2166 # endif
2167 # ifdef SIGPHONE
2168       sys_siglist[SIGWIND] = "SIGPHONE";
2169 # endif
2170 # ifdef SIGPIPE
2171       sys_siglist[SIGPIPE] = "Broken pipe";
2172 # endif
2173 # ifdef SIGPOLL
2174       sys_siglist[SIGPOLL] = "Pollable event occurred";
2175 # endif
2176 # ifdef SIGPROF
2177       sys_siglist[SIGPROF] = "Profiling timer expired";
2178 # endif
2179 # ifdef SIGPTY
2180       sys_siglist[SIGPTY] = "PTY I/O interrupt";
2181 # endif
2182 # ifdef SIGPWR
2183       sys_siglist[SIGPWR] = "Power-fail restart";
2184 # endif
2185 # ifdef SIGQUIT
2186       sys_siglist[SIGQUIT] = "Quit";
2187 # endif
2188 # ifdef SIGRETRACT
2189       sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
2190 # endif
2191 # ifdef SIGSAK
2192       sys_siglist[SIGSAK] = "Secure attention";
2193 # endif
2194 # ifdef SIGSEGV
2195       sys_siglist[SIGSEGV] = "Segmentation violation";
2196 # endif
2197 # ifdef SIGSOUND
2198       sys_siglist[SIGSOUND] = "Sound completed";
2199 # endif
2200 # ifdef SIGSTOP
2201       sys_siglist[SIGSTOP] = "Stopped (signal)";
2202 # endif
2203 # ifdef SIGSTP
2204       sys_siglist[SIGSTP] = "Stopped (user)";
2205 # endif
2206 # ifdef SIGSYS
2207       sys_siglist[SIGSYS] = "Bad argument to system call";
2208 # endif
2209 # ifdef SIGTERM
2210       sys_siglist[SIGTERM] = "Terminated";
2211 # endif
2212 # ifdef SIGTHAW
2213       sys_siglist[SIGTHAW] = "SIGTHAW";
2214 # endif
2215 # ifdef SIGTRAP
2216       sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
2217 # endif
2218 # ifdef SIGTSTP
2219       sys_siglist[SIGTSTP] = "Stopped (user)";
2220 # endif
2221 # ifdef SIGTTIN
2222       sys_siglist[SIGTTIN] = "Stopped (tty input)";
2223 # endif
2224 # ifdef SIGTTOU
2225       sys_siglist[SIGTTOU] = "Stopped (tty output)";
2226 # endif
2227 # ifdef SIGURG
2228       sys_siglist[SIGURG] = "Urgent I/O condition";
2229 # endif
2230 # ifdef SIGUSR1
2231       sys_siglist[SIGUSR1] = "User defined signal 1";
2232 # endif
2233 # ifdef SIGUSR2
2234       sys_siglist[SIGUSR2] = "User defined signal 2";
2235 # endif
2236 # ifdef SIGVTALRM
2237       sys_siglist[SIGVTALRM] = "Virtual timer expired";
2238 # endif
2239 # ifdef SIGWAITING
2240       sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
2241 # endif
2242 # ifdef SIGWINCH
2243       sys_siglist[SIGWINCH] = "Window size changed";
2244 # endif
2245 # ifdef SIGWIND
2246       sys_siglist[SIGWIND] = "SIGWIND";
2247 # endif
2248 # ifdef SIGXCPU
2249       sys_siglist[SIGXCPU] = "CPU time limit exceeded";
2250 # endif
2251 # ifdef SIGXFSZ
2252       sys_siglist[SIGXFSZ] = "File size limit exceeded";
2253 # endif
2254     }
2255 #endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
2256 }
2257 
2258 #ifndef HAVE_RANDOM
2259 #ifdef random
2260 #define HAVE_RANDOM
2261 #endif
2262 #endif
2263 
2264 /* Figure out how many bits the system's random number generator uses.
2265    `random' and `lrand48' are assumed to return 31 usable bits.
2266    BSD `rand' returns a 31 bit value but the low order bits are unusable;
2267    so we'll shift it and treat it like the 15-bit USG `rand'.  */
2268 
2269 #ifndef RAND_BITS
2270 # ifdef HAVE_RANDOM
2271 #  define RAND_BITS 31
2272 # else /* !HAVE_RANDOM */
2273 #  ifdef HAVE_LRAND48
2274 #   define RAND_BITS 31
2275 #   define random lrand48
2276 #  else /* !HAVE_LRAND48 */
2277 #   define RAND_BITS 15
2278 #   if RAND_MAX == 32767
2279 #    define random rand
2280 #   else /* RAND_MAX != 32767 */
2281 #    if RAND_MAX == 2147483647
2282 #     define random() (rand () >> 16)
2283 #    else /* RAND_MAX != 2147483647 */
2284 #     ifdef USG
2285 #      define random rand
2286 #     else
2287 #      define random() (rand () >> 16)
2288 #     endif /* !USG */
2289 #    endif /* RAND_MAX != 2147483647 */
2290 #   endif /* RAND_MAX != 32767 */
2291 #  endif /* !HAVE_LRAND48 */
2292 # endif /* !HAVE_RANDOM */
2293 #endif /* !RAND_BITS */
2294 
2295 void
2296 seed_random (arg)
2297      long arg;
2298 {
2299 #ifdef HAVE_RANDOM
2300   srandom ((unsigned int)arg);
2301 #else
2302 # ifdef HAVE_LRAND48
2303   srand48 (arg);
2304 # else
2305   srand ((unsigned int)arg);
2306 # endif
2307 #endif
2308 }
2309 
2310 /*
2311  * Build a full Emacs-sized word out of whatever we've got.
2312  * This suffices even for a 64-bit architecture with a 15-bit rand.
2313  */
2314 long
2315 get_random ()
2316 {
2317   long val = random ();
2318 #if VALBITS > RAND_BITS
2319   val = (val << RAND_BITS) ^ random ();
2320 #if VALBITS > 2*RAND_BITS
2321   val = (val << RAND_BITS) ^ random ();
2322 #if VALBITS > 3*RAND_BITS
2323   val = (val << RAND_BITS) ^ random ();
2324 #if VALBITS > 4*RAND_BITS
2325   val = (val << RAND_BITS) ^ random ();
2326 #endif /* need at least 5 */
2327 #endif /* need at least 4 */
2328 #endif /* need at least 3 */
2329 #endif /* need at least 2 */
2330   return val & ((1L << VALBITS) - 1);
2331 }
2332 
2333 #ifndef HAVE_STRERROR
2334 #ifndef WINDOWSNT
2335 char *
2336 strerror (errnum)
2337      int errnum;
2338 {
2339   extern char *sys_errlist[];
2340   extern int sys_nerr;
2341 
2342   if (errnum >= 0 && errnum < sys_nerr)
2343     return sys_errlist[errnum];
2344   return (char *) "Unknown error";
2345 }
2346 #endif /* not WINDOWSNT */
2347 #endif /* ! HAVE_STRERROR */
2348 
2349 int
2350 emacs_open (path, oflag, mode)
2351      const char *path;
2352      int oflag, mode;
2353 {
2354   register int rtnval;
2355 
2356   while ((rtnval = open (path, oflag, mode)) == -1
2357          && (errno == EINTR))
2358     QUIT;
2359   return (rtnval);
2360 }
2361 
2362 int
2363 emacs_close (fd)
2364      int fd;
2365 {
2366   int did_retry = 0;
2367   register int rtnval;
2368 
2369   while ((rtnval = close (fd)) == -1
2370          && (errno == EINTR))
2371     did_retry = 1;
2372 
2373   /* If close is interrupted SunOS 4.1 may or may not have closed the
2374      file descriptor.  If it did the second close will fail with
2375      errno = EBADF.  That means we have succeeded.  */
2376   if (rtnval == -1 && did_retry && errno == EBADF)
2377     return 0;
2378 
2379   return rtnval;
2380 }
2381 
2382 int
2383 emacs_read (fildes, buf, nbyte)
2384      int fildes;
2385      char *buf;
2386      unsigned int nbyte;
2387 {
2388   register int rtnval;
2389 
2390   while ((rtnval = read (fildes, buf, nbyte)) == -1
2391          && (errno == EINTR))
2392     QUIT;
2393   return (rtnval);
2394 }
2395 
2396 int
2397 emacs_write (fildes, buf, nbyte)
2398      int fildes;
2399      const char *buf;
2400      unsigned int nbyte;
2401 {
2402   register int rtnval, bytes_written;
2403 
2404   bytes_written = 0;
2405 
2406   while (nbyte > 0)
2407     {
2408       rtnval = write (fildes, buf, nbyte);
2409 
2410       if (rtnval == -1)
2411         {
2412           if (errno == EINTR)
2413             {
2414 #ifdef SYNC_INPUT
2415               /* I originally used `QUIT' but that might causes files to
2416                  be truncated if you hit C-g in the middle of it.  --Stef  */
2417               process_pending_signals ();
2418 #endif
2419               continue;
2420             }
2421           else
2422             return (bytes_written ? bytes_written : -1);
2423         }
2424 
2425       buf += rtnval;
2426       nbyte -= rtnval;
2427       bytes_written += rtnval;
2428     }
2429   return (bytes_written);
2430 }
2431 
2432 #ifdef USG
2433 /*
2434  *      All of the following are for USG.
2435  *
2436  *      On USG systems the system calls are INTERRUPTIBLE by signals
2437  *      that the user program has elected to catch.  Thus the system call
2438  *      must be retried in these cases.  To handle this without massive
2439  *      changes in the source code, we remap the standard system call names
2440  *      to names for our own functions in sysdep.c that do the system call
2441  *      with retries.  Actually, for portability reasons, it is good
2442  *      programming practice, as this example shows, to limit all actual
2443  *      system calls to a single occurrence in the source.  Sure, this
2444  *      adds an extra level of function call overhead but it is almost
2445  *      always negligible.   Fred Fish, Unisoft Systems Inc.
2446  */
2447 
2448 /*
2449  *      Warning, this function may not duplicate 4.2 action properly
2450  *      under error conditions.
2451  */
2452 
2453 #ifndef MAXPATHLEN
2454 /* In 4.1, param.h fails to define this.  */
2455 #define MAXPATHLEN 1024
2456 #endif
2457 
2458 #ifndef HAVE_GETWD
2459 
2460 char *
2461 getwd (pathname)
2462      char *pathname;
2463 {
2464   char *npath, *spath;
2465   extern char *getcwd ();
2466 
2467   BLOCK_INPUT;                  /* getcwd uses malloc */
2468   spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2469   if (spath == 0)
2470     {
2471       UNBLOCK_INPUT;
2472       return spath;
2473     }
2474   /* On Altos 3068, getcwd can return @hostname/dir, so discard
2475      up to first slash.  Should be harmless on other systems.  */
2476   while (*npath && *npath != '/')
2477     npath++;
2478   strcpy (pathname, npath);
2479   free (spath);                 /* getcwd uses malloc */
2480   UNBLOCK_INPUT;
2481   return pathname;
2482 }
2483 
2484 #endif /* HAVE_GETWD */
2485 
2486 /*
2487  *      Emulate rename using unlink/link.  Note that this is
2488  *      only partially correct.  Also, doesn't enforce restriction
2489  *      that files be of same type (regular->regular, dir->dir, etc).
2490  */
2491 
2492 #ifndef HAVE_RENAME
2493 
2494 rename (from, to)
2495      const char *from;
2496      const char *to;
2497 {
2498   if (access (from, 0) == 0)
2499     {
2500       unlink (to);
2501       if (link (from, to) == 0)
2502         if (unlink (from) == 0)
2503           return (0);
2504     }
2505   return (-1);
2506 }
2507 
2508 #endif
2509 
2510 
2511 #if defined(HPUX) && !defined(HAVE_PERROR)
2512 
2513 /* HPUX curses library references perror, but as far as we know
2514    it won't be called.  Anyway this definition will do for now.  */
2515 
2516 perror ()
2517 {
2518 }
2519 #endif /* HPUX and not HAVE_PERROR */
2520 
2521 #ifndef HAVE_DUP2
2522 
2523 /*
2524  *      Emulate BSD dup2.  First close newd if it already exists.
2525  *      Then, attempt to dup oldd.  If not successful, call dup2 recursively
2526  *      until we are, then close the unsuccessful ones.
2527  */
2528 
2529 dup2 (oldd, newd)
2530      int oldd;
2531      int newd;
2532 {
2533   register int fd, ret;
2534 
2535   emacs_close (newd);
2536 
2537 #ifdef F_DUPFD
2538   return fcntl (oldd, F_DUPFD, newd);
2539 #else
2540   fd = dup (old);
2541   if (fd == -1)
2542     return -1;
2543   if (fd == new)
2544     return new;
2545   ret = dup2 (old,new);
2546   emacs_close (fd);
2547   return ret;
2548 #endif
2549 }
2550 
2551 #endif /* not HAVE_DUP2 */
2552 
2553 /*
2554  *      Gettimeofday.  Simulate as much as possible.  Only accurate
2555  *      to nearest second.  Emacs doesn't use tzp so ignore it for now.
2556  *      Only needed when subprocesses are defined.
2557  */
2558 
2559 #ifdef subprocesses
2560 #ifndef HAVE_GETTIMEOFDAY
2561 #ifdef HAVE_TIMEVAL
2562 
2563 /* ARGSUSED */
2564 int
2565 gettimeofday (tp, tzp)
2566      struct timeval *tp;
2567      struct timezone *tzp;
2568 {
2569   extern long time ();
2570 
2571   tp->tv_sec = time ((long *)0);
2572   tp->tv_usec = 0;
2573   if (tzp != 0)
2574     tzp->tz_minuteswest = -1;
2575   return 0;
2576 }
2577 
2578 #endif
2579 #endif
2580 #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
2581 
2582 /*
2583  *      This function will go away as soon as all the stubs fixed. (fnf)
2584  */
2585 
2586 void
2587 croak (badfunc)
2588      char *badfunc;
2589 {
2590   printf ("%s not yet implemented\r\n", badfunc);
2591   reset_all_sys_modes ();
2592   exit (1);
2593 }
2594 
2595 #endif /* USG */
2596 
2597 /* Directory routines for systems that don't have them. */
2598 
2599 #ifdef SYSV_SYSTEM_DIR
2600 
2601 #include <dirent.h>
2602 
2603 #if !defined (HAVE_CLOSEDIR)
2604 
2605 int
2606 closedir (DIR *dirp /* stream from opendir */)
2607 {
2608   int rtnval;
2609 
2610   rtnval = emacs_close (dirp->dd_fd);
2611   xfree ((char *) dirp);
2612 
2613   return rtnval;
2614 }
2615 #endif /* not HAVE_CLOSEDIR */
2616 #endif /* SYSV_SYSTEM_DIR */
2617 
2618 
2619 int
2620 set_file_times (filename, atime, mtime)
2621      const char *filename;
2622      EMACS_TIME atime, mtime;
2623 {
2624 #ifdef HAVE_UTIMES
2625   struct timeval tv[2];
2626   tv[0] = atime;
2627   tv[1] = mtime;
2628   return utimes (filename, tv);
2629 #else /* not HAVE_UTIMES */
2630   struct utimbuf utb;
2631   utb.actime = EMACS_SECS (atime);
2632   utb.modtime = EMACS_SECS (mtime);
2633   return utime (filename, &utb);
2634 #endif /* not HAVE_UTIMES */
2635 }
2636 
2637 /* mkdir and rmdir functions, for systems which don't have them.  */
2638 
2639 #ifndef HAVE_MKDIR
2640 /*
2641  * Written by Robert Rother, Mariah Corporation, August 1985.
2642  *
2643  * If you want it, it's yours.  All I ask in return is that if you
2644  * figure out how to do this in a Bourne Shell script you send me
2645  * a copy.
2646  *                                      sdcsvax!rmr or rmr@uscd
2647  *
2648  * Severely hacked over by John Gilmore to make a 4.2BSD compatible
2649  * subroutine.  11Mar86; hoptoad!gnu
2650  *
2651  * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
2652  * subroutine didn't return EEXIST.  It does now.
2653  */
2654 
2655 /*
2656  * Make a directory.
2657  */
2658 int
2659 mkdir (dpath, dmode)
2660      char *dpath;
2661      int dmode;
2662 {
2663   int cpid, status, fd;
2664   struct stat statbuf;
2665 
2666   if (stat (dpath, &statbuf) == 0)
2667     {
2668       errno = EEXIST;           /* Stat worked, so it already exists */
2669       return -1;
2670     }
2671 
2672   /* If stat fails for a reason other than non-existence, return error */
2673   if (errno != ENOENT)
2674     return -1;
2675 
2676   synch_process_alive = 1;
2677   switch (cpid = fork ())
2678     {
2679 
2680     case -1:                    /* Error in fork */
2681       return (-1);              /* Errno is set already */
2682 
2683     case 0:                     /* Child process */
2684       /*
2685                  * Cheap hack to set mode of new directory.  Since this
2686                  * child process is going away anyway, we zap its umask.
2687                  * FIXME, this won't suffice to set SUID, SGID, etc. on this
2688                  * directory.  Does anybody care?
2689                  */
2690       status = umask (0);       /* Get current umask */
2691       status = umask (status | (0777 & ~dmode));        /* Set for mkdir */
2692       fd = emacs_open ("/dev/null", O_RDWR, 0);
2693       if (fd >= 0)
2694         {
2695           dup2 (fd, 0);
2696           dup2 (fd, 1);
2697           dup2 (fd, 2);
2698         }
2699       execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
2700       _exit (-1);               /* Can't exec /bin/mkdir */
2701 
2702     default:                    /* Parent process */
2703       wait_for_termination (cpid);
2704     }
2705 
2706   if (synch_process_death != 0 || synch_process_retcode != 0
2707       || synch_process_termsig != 0)
2708     {
2709       errno = EIO;              /* We don't know why, but */
2710       return -1;                /* /bin/mkdir failed */
2711     }
2712 
2713   return 0;
2714 }
2715 #endif /* not HAVE_MKDIR */
2716 
2717 #ifndef HAVE_RMDIR
2718 int
2719 rmdir (dpath)
2720      char *dpath;
2721 {
2722   int cpid, status, fd;
2723   struct stat statbuf;
2724 
2725   if (stat (dpath, &statbuf) != 0)
2726     {
2727       /* Stat just set errno.  We don't have to */
2728       return -1;
2729     }
2730 
2731   synch_process_alive = 1;
2732   switch (cpid = fork ())
2733     {
2734 
2735     case -1:                    /* Error in fork */
2736       return (-1);              /* Errno is set already */
2737 
2738     case 0:                     /* Child process */
2739       fd = emacs_open ("/dev/null", O_RDWR, 0);
2740       if (fd >= 0)
2741         {
2742           dup2 (fd, 0);
2743           dup2 (fd, 1);
2744           dup2 (fd, 2);
2745         }
2746       execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
2747       _exit (-1);               /* Can't exec /bin/rmdir */
2748 
2749     default:                    /* Parent process */
2750       wait_for_termination (cpid);
2751     }
2752 
2753   if (synch_process_death != 0 || synch_process_retcode != 0
2754       || synch_process_termsig != 0)
2755     {
2756       errno = EIO;              /* We don't know why, but */
2757       return -1;                /* /bin/rmdir failed */
2758     }
2759 
2760   return 0;
2761 }
2762 #endif /* !HAVE_RMDIR */
2763 
2764 
2765 #ifndef BSTRING
2766 
2767 #ifndef bzero
2768 
2769 void
2770 bzero (b, length)
2771      register char *b;
2772      register int length;
2773 {
2774   while (length-- > 0)
2775     *b++ = 0;
2776 }
2777 
2778 #endif /* no bzero */
2779 #endif /* BSTRING */
2780 
2781 #if (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY)
2782 #undef bcopy
2783 
2784 /* Saying `void' requires a declaration, above, where bcopy is used
2785    and that declaration causes pain for systems where bcopy is a macro.  */
2786 bcopy (b1, b2, length)
2787      register char *b1;
2788      register char *b2;
2789      register int length;
2790 {
2791   while (length-- > 0)
2792     *b2++ = *b1++;
2793 }
2794 #endif /* (!defined (BSTRING) && !defined (bcopy)) || defined (NEED_BCOPY) */
2795 
2796 #ifndef BSTRING
2797 #ifndef bcmp
2798 int
2799 bcmp (b1, b2, length)   /* This could be a macro! */
2800      register char *b1;
2801      register char *b2;
2802      register int length;
2803 {
2804   while (length-- > 0)
2805     if (*b1++ != *b2++)
2806       return 1;
2807 
2808   return 0;
2809 }
2810 #endif /* no bcmp */
2811 #endif /* not BSTRING */
2812 
2813 #ifndef HAVE_STRSIGNAL
2814 char *
2815 strsignal (code)
2816      int code;
2817 {
2818   char *signame = 0;
2819 
2820   if (0 <= code && code < NSIG)
2821     {
2822       /* Cast to suppress warning if the table has const char *.  */
2823       signame = (char *) sys_siglist[code];
2824     }
2825 
2826   return signame;
2827 }
2828 #endif /* HAVE_STRSIGNAL */
2829 
2830 #ifdef HAVE_TERMIOS
2831 /* For make-serial-process  */
2832 int serial_open (char *port)
2833 {
2834   int fd = -1;
2835 
2836   fd = emacs_open ((char*) port,
2837                    O_RDWR
2838 #ifdef O_NONBLOCK
2839                    | O_NONBLOCK
2840 #else
2841                    | O_NDELAY
2842 #endif
2843 #ifdef O_NOCTTY
2844                    | O_NOCTTY
2845 #endif
2846                    , 0);
2847   if (fd < 0)
2848     {
2849       error ("Could not open %s: %s",
2850              port, emacs_strerror (errno));
2851     }
2852 #ifdef TIOCEXCL
2853   ioctl (fd, TIOCEXCL, (char *) 0);
2854 #endif
2855 
2856   return fd;
2857 }
2858 #endif /* TERMIOS  */
2859 
2860 #ifdef HAVE_TERMIOS
2861 
2862 #if !defined (HAVE_CFMAKERAW)
2863 /* Workaround for targets which are missing cfmakeraw.  */
2864 /* Pasted from man page.  */
2865 static void cfmakeraw (struct termios *termios_p)
2866 {
2867     termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
2868     termios_p->c_oflag &= ~OPOST;
2869     termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
2870     termios_p->c_cflag &= ~(CSIZE|PARENB);
2871     termios_p->c_cflag |= CS8;
2872 }
2873 #endif /* !defined (HAVE_CFMAKERAW */
2874 
2875 #if !defined (HAVE_CFSETSPEED)
2876 /* Workaround for targets which are missing cfsetspeed.  */
2877 static int cfsetspeed (struct termios *termios_p, speed_t vitesse)
2878 {
2879   return (cfsetispeed (termios_p, vitesse)
2880           + cfsetospeed (termios_p, vitesse));
2881 }
2882 #endif
2883 
2884 /* For serial-process-configure  */
2885 void
2886 serial_configure (struct Lisp_Process *p,
2887                       Lisp_Object contact)
2888 {
2889   Lisp_Object childp2 = Qnil;
2890   Lisp_Object tem = Qnil;
2891   struct termios attr;
2892   int err = -1;
2893   char summary[4] = "???"; /* This usually becomes "8N1".  */
2894 
2895   childp2 = Fcopy_sequence (p->childp);
2896 
2897   /* Read port attributes and prepare default configuration.  */
2898   err = tcgetattr (p->outfd, &attr);
2899   if (err != 0)
2900     error ("tcgetattr() failed: %s", emacs_strerror (errno));
2901   cfmakeraw (&attr);
2902 #if defined (CLOCAL)
2903   attr.c_cflag |= CLOCAL;
2904 #endif
2905 #if defined (CREAD)
2906   attr.c_cflag |= CREAD;
2907 #endif
2908 
2909   /* Configure speed.  */
2910   if (!NILP (Fplist_member (contact, QCspeed)))
2911     tem = Fplist_get (contact, QCspeed);
2912   else
2913     tem = Fplist_get (p->childp, QCspeed);
2914   CHECK_NUMBER (tem);
2915   err = cfsetspeed (&attr, XINT (tem));
2916   if (err != 0)
2917     error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
2918   childp2 = Fplist_put (childp2, QCspeed, tem);
2919 
2920   /* Configure bytesize.  */
2921   if (!NILP (Fplist_member (contact, QCbytesize)))
2922     tem = Fplist_get (contact, QCbytesize);
2923   else
2924     tem = Fplist_get (p->childp, QCbytesize);
2925   if (NILP (tem))
2926     tem = make_number (8);
2927   CHECK_NUMBER (tem);
2928   if (XINT (tem) != 7 && XINT (tem) != 8)
2929     error (":bytesize must be nil (8), 7, or 8");
2930   summary[0] = XINT(tem) + '0';
2931 #if defined (CSIZE) && defined (CS7) && defined (CS8)
2932   attr.c_cflag &= ~CSIZE;
2933   attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
2934 #else
2935   /* Don't error on bytesize 8, which should be set by cfmakeraw.  */
2936   if (XINT (tem) != 8)
2937     error ("Bytesize cannot be changed");
2938 #endif
2939   childp2 = Fplist_put (childp2, QCbytesize, tem);
2940 
2941   /* Configure parity.  */
2942   if (!NILP (Fplist_member (contact, QCparity)))
2943     tem = Fplist_get (contact, QCparity);
2944   else
2945     tem = Fplist_get (p->childp, QCparity);
2946   if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
2947     error (":parity must be nil (no parity), `even', or `odd'");
2948 #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
2949   attr.c_cflag &= ~(PARENB | PARODD);
2950   attr.c_iflag &= ~(IGNPAR | INPCK);
2951   if (NILP (tem))
2952     {
2953       summary[1] = 'N';
2954     }
2955   else if (EQ (tem, Qeven))
2956     {
2957       summary[1] = 'E';
2958       attr.c_cflag |= PARENB;
2959       attr.c_iflag |= (IGNPAR | INPCK);
2960     }
2961   else if (EQ (tem, Qodd))
2962     {
2963       summary[1] = 'O';
2964       attr.c_cflag |= (PARENB | PARODD);
2965       attr.c_iflag |= (IGNPAR | INPCK);
2966     }
2967 #else
2968   /* Don't error on no parity, which should be set by cfmakeraw.  */
2969   if (!NILP (tem))
2970     error ("Parity cannot be configured");
2971 #endif
2972   childp2 = Fplist_put (childp2, QCparity, tem);
2973 
2974   /* Configure stopbits.  */
2975   if (!NILP (Fplist_member (contact, QCstopbits)))
2976     tem = Fplist_get (contact, QCstopbits);
2977   else
2978     tem = Fplist_get (p->childp, QCstopbits);
2979   if (NILP (tem))
2980     tem = make_number (1);
2981   CHECK_NUMBER (tem);
2982   if (XINT (tem) != 1 && XINT (tem) != 2)
2983     error (":stopbits must be nil (1 stopbit), 1, or 2");
2984   summary[2] = XINT (tem) + '0';
2985 #if defined (CSTOPB)
2986   attr.c_cflag &= ~CSTOPB;
2987   if (XINT (tem) == 2)
2988     attr.c_cflag |= CSTOPB;
2989 #else
2990   /* Don't error on 1 stopbit, which should be set by cfmakeraw.  */
2991   if (XINT (tem) != 1)
2992     error ("Stopbits cannot be configured");
2993 #endif
2994   childp2 = Fplist_put (childp2, QCstopbits, tem);
2995 
2996   /* Configure flowcontrol.  */
2997   if (!NILP (Fplist_member (contact, QCflowcontrol)))
2998     tem = Fplist_get (contact, QCflowcontrol);
2999   else
3000     tem = Fplist_get (p->childp, QCflowcontrol);
3001   if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
3002     error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
3003 #if defined (CRTSCTS)
3004   attr.c_cflag &= ~CRTSCTS;
3005 #endif
3006 #if defined (CNEW_RTSCTS)
3007   attr.c_cflag &= ~CNEW_RTSCTS;
3008 #endif
3009 #if defined (IXON) && defined (IXOFF)
3010   attr.c_iflag &= ~(IXON | IXOFF);
3011 #endif
3012   if (NILP (tem))
3013     {
3014       /* Already configured.  */
3015     }
3016   else if (EQ (tem, Qhw))
3017     {
3018 #if defined (CRTSCTS)
3019       attr.c_cflag |= CRTSCTS;
3020 #elif defined (CNEW_RTSCTS)
3021       attr.c_cflag |= CNEW_RTSCTS;
3022 #else
3023       error ("Hardware flowcontrol (RTS/CTS) not supported");
3024 #endif
3025     }
3026   else if (EQ (tem, Qsw))
3027     {
3028 #if defined (IXON) && defined (IXOFF)
3029       attr.c_iflag |= (IXON | IXOFF);
3030 #else
3031       error ("Software flowcontrol (XON/XOFF) not supported");
3032 #endif
3033     }
3034   childp2 = Fplist_put (childp2, QCflowcontrol, tem);
3035 
3036   /* Activate configuration.  */
3037   err = tcsetattr (p->outfd, TCSANOW, &attr);
3038   if (err != 0)
3039     error ("tcsetattr() failed: %s", emacs_strerror (errno));
3040 
3041   childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
3042   p->childp = childp2;
3043 
3044 }
3045 #endif /* TERMIOS  */
3046 
3047 /* System depended enumeration of and access to system processes a-la ps(1).  */
3048 
3049 #ifdef HAVE_PROCFS
3050 
3051 /* Process enumeration and access via /proc.  */
3052 
3053 Lisp_Object
3054 list_system_processes ()
3055 {
3056   Lisp_Object procdir, match, proclist, next;
3057   struct gcpro gcpro1, gcpro2;
3058   register Lisp_Object tail;
3059 
3060   GCPRO2 (procdir, match);
3061   /* For every process on the system, there's a directory in the
3062      "/proc" pseudo-directory whose name is the numeric ID of that
3063      process.  */
3064   procdir = build_string ("/proc");
3065   match = build_string ("[0-9]+");
3066   proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
3067 
3068   /* `proclist' gives process IDs as strings.  Destructively convert
3069      each string into a number.  */
3070   for (tail = proclist; CONSP (tail); tail = next)
3071     {
3072       next = XCDR (tail);
3073       XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
3074     }
3075   UNGCPRO;
3076 
3077   /* directory_files_internal returns the files in reverse order; undo
3078      that.  */
3079   proclist = Fnreverse (proclist);
3080   return proclist;
3081 }
3082 
3083 /* The WINDOWSNT implementation is in w32.c.
3084    The MSDOS implementation is in dosfns.c.  */
3085 #elif !defined (WINDOWSNT) && !defined (MSDOS)
3086 
3087 Lisp_Object
3088 list_system_processes ()
3089 {
3090   return Qnil;
3091 }
3092 
3093 #endif /* !defined (WINDOWSNT) */
3094 
3095 #ifdef GNU_LINUX
3096 static void
3097 time_from_jiffies (unsigned long long tval, long hz,
3098                    time_t *sec, unsigned *usec)
3099 {
3100   unsigned long long ullsec;
3101 
3102   *sec = tval / hz;
3103   ullsec = *sec;
3104   tval -= ullsec * hz;
3105   /* Careful: if HZ > 1 million, then integer division by it yields zero.  */
3106   if (hz <= 1000000)
3107     *usec = tval * 1000000 / hz;
3108   else
3109     *usec = tval / (hz / 1000000);
3110 }
3111 
3112 static Lisp_Object
3113 ltime_from_jiffies (unsigned long long tval, long hz)
3114 {
3115   time_t sec;
3116   unsigned usec;
3117 
3118   time_from_jiffies (tval, hz, &sec, &usec);
3119 
3120   return list3 (make_number ((sec >> 16) & 0xffff),
3121                 make_number (sec & 0xffff),
3122                 make_number (usec));
3123 }
3124 
3125 static void
3126 get_up_time (time_t *sec, unsigned *usec)
3127 {
3128   FILE *fup;
3129 
3130   *sec = *usec = 0;
3131 
3132   BLOCK_INPUT;
3133   fup = fopen ("/proc/uptime", "r");
3134 
3135   if (fup)
3136     {
3137       double uptime, idletime;
3138 
3139       /* The numbers in /proc/uptime use C-locale decimal point, but
3140          we already set ourselves to the C locale (see `fixup_locale'
3141          in emacs.c).  */
3142       if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
3143         {
3144           *sec = uptime;
3145           *usec = (uptime - *sec) * 1000000;
3146         }
3147       fclose (fup);
3148     }
3149   UNBLOCK_INPUT;
3150 }
3151 
3152 #define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
3153 #define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
3154 
3155 static Lisp_Object
3156 procfs_ttyname (int rdev)
3157 {
3158   FILE *fdev = NULL;
3159   char name[PATH_MAX];
3160 
3161   BLOCK_INPUT;
3162   fdev = fopen ("/proc/tty/drivers", "r");
3163 
3164   if (fdev)
3165     {
3166       unsigned major;
3167       unsigned long minor_beg, minor_end;
3168       char minor[25];   /* 2 32-bit numbers + dash */
3169       char *endp;
3170 
3171       while (!feof (fdev) && !ferror (fdev))
3172         {
3173           if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
3174               && major == MAJOR (rdev))
3175             {
3176               minor_beg = strtoul (minor, &endp, 0);
3177               if (*endp == '\0')
3178                 minor_end = minor_beg;
3179               else if (*endp == '-')
3180                 minor_end = strtoul (endp + 1, &endp, 0);
3181               else
3182                 continue;
3183 
3184               if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
3185                 {
3186                   sprintf (name + strlen (name), "%u", MINOR (rdev));
3187                   break;
3188                 }
3189             }
3190         }
3191       fclose (fdev);
3192     }
3193   UNBLOCK_INPUT;
3194   return build_string (name);
3195 }
3196 
3197 static unsigned long
3198 procfs_get_total_memory (void)
3199 {
3200   FILE *fmem = NULL;
3201   unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
3202 
3203   BLOCK_INPUT;
3204   fmem = fopen ("/proc/meminfo", "r");
3205 
3206   if (fmem)
3207     {
3208       unsigned long entry_value;
3209       char entry_name[20];      /* the longest I saw is 13+1 */
3210 
3211       while (!feof (fmem) && !ferror (fmem))
3212         {
3213           if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
3214               && strcmp (entry_name, "MemTotal:") == 0)
3215             {
3216               retval = entry_value;
3217               break;
3218             }
3219         }
3220       fclose (fmem);
3221     }
3222   UNBLOCK_INPUT;
3223   return retval;
3224 }
3225 
3226 Lisp_Object
3227 system_process_attributes (Lisp_Object pid)
3228 {
3229   char procfn[PATH_MAX], fn[PATH_MAX];
3230   struct stat st;
3231   struct passwd *pw;
3232   struct group *gr;
3233   long clocks_per_sec;
3234   char *procfn_end;
3235   char procbuf[1025], *p, *q;
3236   int fd;
3237   ssize_t nread;
3238   const char *cmd = NULL;
3239   char *cmdline = NULL;
3240   size_t cmdsize = 0, cmdline_size;
3241   unsigned char c;
3242   int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
3243   unsigned long long utime, stime, cutime, cstime, start;
3244   long priority, nice, rss;
3245   unsigned long minflt, majflt, cminflt, cmajflt, vsize;
3246   time_t sec;
3247   unsigned usec;
3248   EMACS_TIME tnow, tstart, tboot, telapsed;
3249   double pcpu, pmem;
3250   Lisp_Object attrs = Qnil;
3251   Lisp_Object cmd_str, decoded_cmd, tem;
3252   struct gcpro gcpro1, gcpro2;
3253   EMACS_INT uid_eint, gid_eint;
3254 
3255   CHECK_NUMBER_OR_FLOAT (pid);
3256   proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
3257   sprintf (procfn, "/proc/%u", proc_id);
3258   if (stat (procfn, &st) < 0)
3259     return attrs;
3260 
3261   GCPRO2 (attrs, decoded_cmd);
3262 
3263   /* euid egid */
3264   uid = st.st_uid;
3265   /* Use of EMACS_INT stops GCC whining about limited range of data type.  */
3266   uid_eint = uid;
3267   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
3268   BLOCK_INPUT;
3269   pw = getpwuid (uid);
3270   UNBLOCK_INPUT;
3271   if (pw)
3272     attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3273 
3274   gid = st.st_gid;
3275   gid_eint = gid;
3276   attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
3277   BLOCK_INPUT;
3278   gr = getgrgid (gid);
3279   UNBLOCK_INPUT;
3280   if (gr)
3281     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3282 
3283   strcpy (fn, procfn);
3284   procfn_end = fn + strlen (fn);
3285   strcpy (procfn_end, "/stat");
3286   fd = emacs_open (fn, O_RDONLY, 0);
3287   if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof(procbuf) - 1)) > 0)
3288     {
3289       procbuf[nread] = '\0';
3290       p = procbuf;
3291 
3292       p = strchr (p, '(');
3293       if (p != NULL)
3294         {
3295           q = strrchr (p + 1, ')');
3296           /* comm */
3297           if (q != NULL)
3298             {
3299               cmd = p + 1;
3300               cmdsize = q - cmd;
3301             }
3302         }
3303       else
3304         q = NULL;
3305       if (cmd == NULL)
3306         {
3307           cmd = "???";
3308           cmdsize = 3;
3309         }
3310       /* Command name is encoded in locale-coding-system; decode it.  */
3311       cmd_str = make_unibyte_string (cmd, cmdsize);
3312       decoded_cmd = code_convert_string_norecord (cmd_str,
3313                                                   Vlocale_coding_system, 0);
3314       attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3315 
3316       if (q)
3317         {
3318           EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
3319           p = q + 2;
3320           /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
3321           sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
3322                   &c, &ppid, &pgrp, &sess, &tty, &tpgid,
3323                   &minflt, &cminflt, &majflt, &cmajflt,
3324                   &utime, &stime, &cutime, &cstime,
3325                   &priority, &nice, &thcount, &start, &vsize, &rss);
3326           {
3327             char state_str[2];
3328 
3329             state_str[0] = c;
3330             state_str[1] = '\0';
3331             tem =  build_string (state_str);
3332             attrs = Fcons (Fcons (Qstate, tem), attrs);
3333           }
3334           /* Stops GCC whining about limited range of data type.  */
3335           ppid_eint = ppid;
3336           pgrp_eint = pgrp;
3337           sess_eint = sess;
3338           tpgid_eint = tpgid;
3339           thcount_eint = thcount;
3340           attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
3341           attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
3342           attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
3343           attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
3344           attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
3345           attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
3346           attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
3347           attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
3348           attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
3349           clocks_per_sec = sysconf (_SC_CLK_TCK);
3350           if (clocks_per_sec < 0)
3351             clocks_per_sec = 100;
3352           attrs = Fcons (Fcons (Qutime,
3353                                 ltime_from_jiffies (utime, clocks_per_sec)),
3354                          attrs);
3355           attrs = Fcons (Fcons (Qstime,
3356                                 ltime_from_jiffies (stime, clocks_per_sec)),
3357                          attrs);
3358           attrs = Fcons (Fcons (Qtime,
3359                                 ltime_from_jiffies (stime+utime, clocks_per_sec)),
3360                          attrs);
3361           attrs = Fcons (Fcons (Qcutime,
3362                                 ltime_from_jiffies (cutime, clocks_per_sec)),
3363                          attrs);
3364           attrs = Fcons (Fcons (Qcstime,
3365                                 ltime_from_jiffies (cstime, clocks_per_sec)),
3366                          attrs);
3367           attrs = Fcons (Fcons (Qctime,
3368                                 ltime_from_jiffies (cstime+cutime, clocks_per_sec)),
3369                          attrs);
3370           attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
3371           attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
3372           attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
3373           EMACS_GET_TIME (tnow);
3374           get_up_time (&sec, &usec);
3375           EMACS_SET_SECS (telapsed, sec);
3376           EMACS_SET_USECS (telapsed, usec);
3377           EMACS_SUB_TIME (tboot, tnow, telapsed);
3378           time_from_jiffies (start, clocks_per_sec, &sec, &usec);
3379           EMACS_SET_SECS (tstart, sec);
3380           EMACS_SET_USECS (tstart, usec);
3381           EMACS_ADD_TIME (tstart, tboot, tstart);
3382           attrs = Fcons (Fcons (Qstart,
3383                                 list3 (make_number
3384                                        ((EMACS_SECS (tstart) >> 16) & 0xffff),
3385                                        make_number
3386                                        (EMACS_SECS (tstart) & 0xffff),
3387                                        make_number
3388                                        (EMACS_USECS (tstart)))),
3389                          attrs);
3390           attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
3391           attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
3392           EMACS_SUB_TIME (telapsed, tnow, tstart);
3393           attrs = Fcons (Fcons (Qetime,
3394                                 list3 (make_number
3395                                        ((EMACS_SECS (telapsed) >> 16) & 0xffff),
3396                                        make_number
3397                                        (EMACS_SECS (telapsed) & 0xffff),
3398                                        make_number
3399                                        (EMACS_USECS (telapsed)))),
3400                          attrs);
3401           time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec);
3402           pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
3403           if (pcpu > 1.0)
3404             pcpu = 1.0;
3405           attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
3406           pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
3407           if (pmem > 100)
3408             pmem = 100;
3409           attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
3410         }
3411     }
3412   if (fd >= 0)
3413     emacs_close (fd);
3414 
3415   /* args */
3416   strcpy (procfn_end, "/cmdline");
3417   fd = emacs_open (fn, O_RDONLY, 0);
3418   if (fd >= 0)
3419     {
3420       for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
3421         {
3422           if (isspace (c) || c == '\\')
3423             cmdline_size++;     /* for later quoting, see below */
3424         }
3425       if (cmdline_size)
3426         {
3427           cmdline = xmalloc (cmdline_size + 1);
3428           lseek (fd, 0L, SEEK_SET);
3429           cmdline[0] = '\0';
3430           if ((nread = read (fd, cmdline, cmdline_size)) >= 0)
3431             cmdline[nread++] = '\0';
3432           else
3433             {
3434               /* Assigning zero to `nread' makes us skip the following
3435                  two loops, assign zero to cmdline_size, and enter the
3436                  following `if' clause that handles unknown command
3437                  lines.  */
3438               nread = 0;
3439             }
3440           /* We don't want trailing null characters.  */
3441           for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
3442             nread--;
3443           for (p = cmdline; p < cmdline + nread; p++)
3444             {
3445               /* Escape-quote whitespace and backslashes.  */
3446               if (isspace (*p) || *p == '\\')
3447                 {
3448                   memmove (p + 1, p, nread - (p - cmdline));
3449                   nread++;
3450                   *p++ = '\\';
3451                 }
3452               else if (*p == '\0')
3453                 *p = ' ';
3454             }
3455           cmdline_size = nread;
3456         }
3457       if (!cmdline_size)
3458         {
3459           if (!cmd)
3460             cmd = "???";
3461           if (!cmdsize)
3462             cmdsize = strlen (cmd);
3463           cmdline_size = cmdsize + 2;
3464           cmdline = xmalloc (cmdline_size + 1);
3465           strcpy (cmdline, "[");
3466           strcat (strncat (cmdline, cmd, cmdsize), "]");
3467         }
3468       emacs_close (fd);
3469       /* Command line is encoded in locale-coding-system; decode it.  */
3470       cmd_str = make_unibyte_string (cmdline, cmdline_size);
3471       decoded_cmd = code_convert_string_norecord (cmd_str,
3472                                                   Vlocale_coding_system, 0);
3473       xfree (cmdline);
3474       attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3475     }
3476 
3477   UNGCPRO;
3478   return attrs;
3479 }
3480 
3481 #elif defined (SOLARIS2) && defined (HAVE_PROCFS)
3482 
3483 /* The <procfs.h> header does not like to be included if _LP64 is defined and
3484    __FILE_OFFSET_BITS == 64.  This is an ugly workaround that.  */
3485 #if !defined (_LP64) && defined (_FILE_OFFSET_BITS) &&  (_FILE_OFFSET_BITS  ==  64)
3486 #define PROCFS_FILE_OFFSET_BITS_HACK 1
3487 #undef _FILE_OFFSET_BITS
3488 #else
3489 #define PROCFS_FILE_OFFSET_BITS_HACK 0
3490 #endif
3491 
3492 #include <procfs.h>
3493 
3494 #if PROCFS_FILE_OFFSET_BITS_HACK ==  1
3495 #define _FILE_OFFSET_BITS 64
3496 #endif /* PROCFS_FILE_OFFSET_BITS_HACK ==  1 */
3497 
3498 Lisp_Object
3499 system_process_attributes (Lisp_Object pid)
3500 {
3501   char procfn[PATH_MAX], fn[PATH_MAX];
3502   struct stat st;
3503   struct passwd *pw;
3504   struct group *gr;
3505   char *procfn_end;
3506   struct psinfo pinfo;
3507   int fd;
3508   ssize_t nread;
3509   int proc_id, uid, gid;
3510   Lisp_Object attrs = Qnil;
3511   Lisp_Object decoded_cmd, tem;
3512   struct gcpro gcpro1, gcpro2;
3513   EMACS_INT uid_eint, gid_eint;
3514 
3515   CHECK_NUMBER_OR_FLOAT (pid);
3516   proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
3517   sprintf (procfn, "/proc/%u", proc_id);
3518   if (stat (procfn, &st) < 0)
3519     return attrs;
3520 
3521   GCPRO2 (attrs, decoded_cmd);
3522 
3523   /* euid egid */
3524   uid = st.st_uid;
3525   /* Use of EMACS_INT stops GCC whining about limited range of data type.  */
3526   uid_eint = uid;
3527   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
3528   BLOCK_INPUT;
3529   pw = getpwuid (uid);
3530   UNBLOCK_INPUT;
3531   if (pw)
3532     attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3533 
3534   gid = st.st_gid;
3535   gid_eint = gid;
3536   attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
3537   BLOCK_INPUT;
3538   gr = getgrgid (gid);
3539   UNBLOCK_INPUT;
3540   if (gr)
3541     attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3542 
3543   strcpy (fn, procfn);
3544   procfn_end = fn + strlen (fn);
3545   strcpy (procfn_end, "/psinfo");
3546   fd = emacs_open (fn, O_RDONLY, 0);
3547   if (fd >= 0
3548       && (nread = read (fd, (char*)&pinfo, sizeof(struct psinfo)) > 0))
3549     {
3550           attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (pinfo.pr_ppid)), attrs);
3551           attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pinfo.pr_pgid)), attrs);
3552           attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (pinfo.pr_sid)), attrs);
3553 
3554           {
3555             char state_str[2];
3556             state_str[0] =  pinfo.pr_lwp.pr_sname;
3557             state_str[1] =  '\0';
3558             tem =   build_string (state_str);
3559             attrs =  Fcons (Fcons (Qstate,  tem),  attrs);
3560           }
3561 
3562           /* FIXME: missing Qttyname. psinfo.pr_ttydev is a dev_t,
3563              need to get a string from it. */
3564 
3565           /* FIXME: missing: Qtpgid */
3566 
3567           /* FIXME: missing:
3568                 Qminflt
3569                 Qmajflt
3570                 Qcminflt
3571                 Qcmajflt
3572 
3573                 Qutime
3574                 Qcutime
3575                 Qstime
3576                 Qcstime
3577                 Are they available? */
3578 
3579           attrs = Fcons (Fcons (Qtime,
3580                                 list3 (make_number (pinfo.pr_time.tv_sec >> 16),
3581                                        make_number (pinfo.pr_time.tv_sec & 0xffff),
3582                                        make_number (pinfo.pr_time.tv_nsec))),
3583                          attrs);
3584 
3585           attrs = Fcons (Fcons (Qctime,
3586                                 list3 (make_number (pinfo.pr_ctime.tv_sec >> 16),
3587                                        make_number (pinfo.pr_ctime.tv_sec & 0xffff),
3588                                        make_number (pinfo.pr_ctime.tv_nsec))),
3589                          attrs);
3590 
3591           attrs = Fcons (Fcons (Qpri, make_number (pinfo.pr_lwp.pr_pri)), attrs);
3592           attrs = Fcons (Fcons (Qnice, make_number (pinfo.pr_lwp.pr_nice)), attrs);
3593           attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (pinfo.pr_nlwp)), attrs);
3594 
3595           attrs = Fcons (Fcons (Qstart,
3596                                 list3 (make_number (pinfo.pr_start.tv_sec >> 16),
3597                                        make_number (pinfo.pr_start.tv_sec & 0xffff),
3598                                        make_number (pinfo.pr_start.tv_nsec))),
3599                          attrs);
3600           attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (pinfo.pr_size)), attrs);
3601           attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (pinfo.pr_rssize)), attrs);
3602 
3603           /* pr_pctcpu and pr_pctmem are encoded as a fixed point 16 bit number in  [0 ... 1].  */
3604           attrs = Fcons (Fcons (Qpcpu, (pinfo.pr_pctcpu * 100.0) / (double)0x8000), attrs);
3605           attrs = Fcons (Fcons (Qpmem, (pinfo.pr_pctmem * 100.0) / (double)0x8000), attrs);
3606 
3607           decoded_cmd
3608             =  code_convert_string_norecord (make_unibyte_string (pinfo.pr_fname,
3609                                                                   strlen (pinfo.pr_fname)),
3610                                              Vlocale_coding_system,  0);
3611           attrs =  Fcons (Fcons (Qcomm,  decoded_cmd),  attrs);
3612           decoded_cmd
3613             =  code_convert_string_norecord (make_unibyte_string (pinfo.pr_psargs,
3614                                                                   strlen (pinfo.pr_psargs)),
3615                                              Vlocale_coding_system,  0);
3616           attrs =  Fcons (Fcons (Qargs,  decoded_cmd),  attrs);
3617     }
3618 
3619   if (fd >= 0)
3620     emacs_close (fd);
3621 
3622   UNGCPRO;
3623   return attrs;
3624 }
3625 
3626 /* The WINDOWSNT implementation is in w32.c.
3627    The MSDOS implementation is in dosfns.c.  */
3628 #elif !defined (WINDOWSNT) && !defined (MSDOS)
3629 
3630 Lisp_Object
3631 system_process_attributes (Lisp_Object pid)
3632 {
3633   return Qnil;
3634 }
3635 
3636 #endif  /* !defined (WINDOWSNT) */
3637 
3638 
3639 /* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
3640    (do not change this comment) */