sysdep.c 86 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Interfaces to system-dependent kernel and library entries.
2
   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
Glenn Morris's avatar
Glenn Morris committed
3
                 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Glenn Morris's avatar
Glenn Morris committed
4
                 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
5 6 7

This file is part of GNU Emacs.

8
GNU Emacs is free software: you can redistribute it and/or modify
Jim Blandy's avatar
Jim Blandy committed
9
it under the terms of the GNU General Public License as published by
10 11
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jim Blandy's avatar
Jim Blandy committed
12 13 14 15 16 17 18

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

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/>.  */
Jim Blandy's avatar
Jim Blandy committed
20

Pavel Janík's avatar
Pavel Janík committed
21
#include <config.h>
22
#include <ctype.h>
Jim Blandy's avatar
Jim Blandy committed
23
#include <signal.h>
24
#include <stdio.h>
Jim Blandy's avatar
Jim Blandy committed
25
#include <setjmp.h>
26 27 28 29 30 31 32
#ifdef HAVE_PWD_H
#include <pwd.h>
#include <grp.h>
#endif /* HAVE_PWD_H */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif /* HAVE_LIMITS_H */
33 34 35
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
Dan Nicolaescu's avatar
Dan Nicolaescu committed
36

Jim Blandy's avatar
Jim Blandy committed
37
#include "lisp.h"
38 39 40
/* Including stdlib.h isn't necessarily enough to get srandom
   declared, e.g. without __USE_XOPEN_EXTENDED with glibc 2.  */

41 42 43
/* The w32 build defines select stuff in w32.h, which is included by
   sys/select.h (included below).   */
#ifndef WINDOWSNT
44
#include "sysselect.h"
45
#endif
46

47
#include "blockinput.h"
Jim Blandy's avatar
Jim Blandy committed
48

49
#ifdef WINDOWSNT
50 51
#define read sys_read
#define write sys_write
52
#include <windows.h>
53 54 55
#ifndef NULL
#define NULL 0
#endif
56 57
#endif /* not WINDOWSNT */

Jim Blandy's avatar
Jim Blandy committed
58 59 60 61
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

62
#ifdef HAVE_SETPGID
Dan Nicolaescu's avatar
Dan Nicolaescu committed
63
#if !defined (USG)
64
#undef setpgrp
65 66
#define setpgrp setpgid
#endif
67
#endif
68

69 70 71 72 73
/* Get SI_SRPC_DOMAIN, if it is available.  */
#ifdef HAVE_SYS_SYSTEMINFO_H
#include <sys/systeminfo.h>
#endif

74 75 76 77 78
#ifdef MSDOS	/* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
#include <dos.h>
#include "dosfns.h"
#include "msdos.h"
#include <sys/param.h>
79
#endif
80

81
#include <sys/file.h>
82

83
#ifdef HAVE_FCNTL_H
84 85
#include <fcntl.h>
#endif
Jim Blandy's avatar
Jim Blandy committed
86

87
#ifndef MSDOS
Jim Blandy's avatar
Jim Blandy committed
88
#include <sys/ioctl.h>
89
#endif
90

91
#include "systty.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
92
#include "syswait.h"
Jim Blandy's avatar
Jim Blandy committed
93

Dan Nicolaescu's avatar
Dan Nicolaescu committed
94
#if defined (USG)
Jim Blandy's avatar
Jim Blandy committed
95 96
#include <sys/utsname.h>
#include <memory.h>
Dan Nicolaescu's avatar
Dan Nicolaescu committed
97
#endif /* USG */
Jim Blandy's avatar
Jim Blandy committed
98 99 100

extern int quit_char;

101
#include "keyboard.h"
Jim Blandy's avatar
Jim Blandy committed
102
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
103 104 105 106 107 108
#include "window.h"
#include "termhooks.h"
#include "termchar.h"
#include "termopts.h"
#include "dispextern.h"
#include "process.h"
Karoly Lorentey's avatar
Karoly Lorentey committed
109
#include "cm.h"  /* for reset_sys_modes */
Jim Blandy's avatar
Jim Blandy committed
110

Glenn Morris's avatar
Glenn Morris committed
111
/* For serial_configure and serial_open.  */
112 113 114 115
extern Lisp_Object QCport, QCspeed, QCprocess;
extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;

116 117 118 119
#ifdef WINDOWSNT
#include <direct.h>
/* In process.h which conflicts with the local copy.  */
#define _P_WAIT 0
120 121
int _cdecl _spawnlp (int, const char *, const char *, ...);
int _cdecl _getpid (void);
122
extern char *getwd (char *);
123 124
#endif

Jim Blandy's avatar
Jim Blandy committed
125 126
#include "syssignal.h"
#include "systime.h"
127 128 129 130 131 132 133 134 135 136 137 138 139 140
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif

#ifndef HAVE_UTIMES
#ifndef HAVE_STRUCT_UTIMBUF
/* We want to use utime rather than utimes, but we couldn't find the
   structure declaration.  We'll use the traditional one.  */
struct utimbuf {
  long actime;
  long modtime;
};
#endif
#endif
Jim Blandy's avatar
Jim Blandy committed
141

142 143 144 145 146
/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
#ifndef LPASS8
#define LPASS8 0
#endif

147
static const int baud_convert[] =
Jim Blandy's avatar
Jim Blandy committed
148 149 150 151 152
  {
    0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
    1800, 2400, 4800, 9600, 19200, 38400
  };

153 154 155
#ifdef HAVE_SPEED_T
#include <termios.h>
#else
156 157
#if defined (HAVE_LIBNCURSES) && ! defined (NCURSES_OSPEED_T)
#else
158
#if defined (HAVE_TERMIOS_H) && defined (GNU_LINUX)
Richard M. Stallman's avatar
Richard M. Stallman committed
159
#include <termios.h>
160
#endif
161
#endif
162
#endif
Jim Blandy's avatar
Jim Blandy committed
163

Gerd Moellmann's avatar
Gerd Moellmann committed
164 165
int emacs_ospeed;

166
void croak (char *) NO_RETURN;
167

168 169 170 171
/* Temporary used by `sigblock' when defined in terms of signprocmask.  */

SIGMASKTYPE sigprocmask_set;

172

173
#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
174

175
/* Return the current working directory.  Returns NULL on errors.
176 177 178
   Any other returned value must be freed with free. This is used
   only when get_current_dir_name is not defined on the system.  */
char*
179
get_current_dir_name (void)
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
{
  char *buf;
  char *pwd;
  struct stat dotstat, pwdstat;
  /* If PWD is accurate, use it instead of calling getwd.  PWD is
     sometimes a nicer name, and using it may avoid a fatal error if a
     parent directory is searchable but not readable.  */
    if ((pwd = getenv ("PWD")) != 0
      && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
      && stat (pwd, &pwdstat) == 0
      && stat (".", &dotstat) == 0
      && dotstat.st_ino == pwdstat.st_ino
      && dotstat.st_dev == pwdstat.st_dev
#ifdef MAXPATHLEN
      && strlen (pwd) < MAXPATHLEN
#endif
      )
    {
      buf = (char *) malloc (strlen (pwd) + 1);
      if (!buf)
        return NULL;
      strcpy (buf, pwd);
    }
#ifdef HAVE_GETCWD
  else
    {
      size_t buf_size = 1024;
207
      buf = (char *) malloc (buf_size);
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
      if (!buf)
        return NULL;
      for (;;)
        {
          if (getcwd (buf, buf_size) == buf)
            break;
          if (errno != ERANGE)
            {
              int tmp_errno = errno;
              free (buf);
              errno = tmp_errno;
              return NULL;
            }
          buf_size *= 2;
          buf = (char *) realloc (buf, buf_size);
          if (!buf)
            return NULL;
        }
    }
#else
  else
    {
      /* We need MAXPATHLEN here.  */
      buf = (char *) malloc (MAXPATHLEN + 1);
      if (!buf)
        return NULL;
      if (getwd (buf) == NULL)
        {
          int tmp_errno = errno;
          free (buf);
          errno = tmp_errno;
          return NULL;
        }
    }
#endif
  return buf;
}
#endif

247

248
/* Discard pending input on all input descriptors.  */
Jim Blandy's avatar
Jim Blandy committed
249

250
void
251
discard_tty_input (void)
Jim Blandy's avatar
Jim Blandy committed
252
{
253
#ifndef WINDOWSNT
Jim Blandy's avatar
Jim Blandy committed
254
  struct emacs_tty buf;
Jim Blandy's avatar
Jim Blandy committed
255 256 257 258

  if (noninteractive)
    return;

259
#ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
260
  while (dos_keyread () != -1)
261
    ;
262
#else /* not MSDOS */
263
  {
264
    struct tty_display_info *tty;
265 266
    for (tty = tty_list; tty; tty = tty->next)
      {
267 268 269 270 271
        if (tty->input)         /* Is the device suspended? */
          {
            EMACS_GET_TTY (fileno (tty->input), &buf);
            EMACS_SET_TTY (fileno (tty->input), &buf, 0);
          }
272 273
      }
  }
274
#endif /* not MSDOS */
275
#endif /* not WINDOWSNT */
Jim Blandy's avatar
Jim Blandy committed
276 277
}

278

Jim Blandy's avatar
Jim Blandy committed
279 280
#ifdef SIGTSTP

281
/* Arrange for character C to be read as the next input from
282 283 284
   the terminal.
   XXX What if we have multiple ttys?
*/
285

Andreas Schwab's avatar
Andreas Schwab committed
286
void
287
stuff_char (char c)
Jim Blandy's avatar
Jim Blandy committed
288
{
289
  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
290 291
    return;

Jim Blandy's avatar
Jim Blandy committed
292 293
/* Should perhaps error if in batch mode */
#ifdef TIOCSTI
294
  ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
Jim Blandy's avatar
Jim Blandy committed
295
#else /* no TIOCSTI */
296
  error ("Cannot stuff terminal input characters in this version of Unix");
Jim Blandy's avatar
Jim Blandy committed
297 298 299 300
#endif /* no TIOCSTI */
}

#endif /* SIGTSTP */
301

302
void
303
init_baud_rate (int fd)
Jim Blandy's avatar
Jim Blandy committed
304 305
{
  if (noninteractive)
Gerd Moellmann's avatar
Gerd Moellmann committed
306
    emacs_ospeed = 0;
Jim Blandy's avatar
Jim Blandy committed
307 308
  else
    {
309
#ifdef DOS_NT
Gerd Moellmann's avatar
Gerd Moellmann committed
310
    emacs_ospeed = 15;
311
#else  /* not DOS_NT */
312 313
#ifdef HAVE_TERMIOS
      struct termios sg;
Jim Blandy's avatar
Jim Blandy committed
314

315
      sg.c_cflag = B9600;
316
      tcgetattr (fd, &sg);
Gerd Moellmann's avatar
Gerd Moellmann committed
317
      emacs_ospeed = cfgetospeed (&sg);
Dan Nicolaescu's avatar
Dan Nicolaescu committed
318
#else /* not TERMIOS */
319 320
#ifdef HAVE_TERMIO
      struct termio sg;
Jim Blandy's avatar
Jim Blandy committed
321

322
      sg.c_cflag = B9600;
323
#ifdef HAVE_TCATTR
324
      tcgetattr (fd, &sg);
325
#else
326
      ioctl (fd, TCGETA, &sg);
327
#endif
Gerd Moellmann's avatar
Gerd Moellmann committed
328
      emacs_ospeed = sg.c_cflag & CBAUD;
Dan Nicolaescu's avatar
Dan Nicolaescu committed
329
#else /* neither TERMIOS nor TERMIO */
Jim Blandy's avatar
Jim Blandy committed
330
      struct sgttyb sg;
331

Jim Blandy's avatar
Jim Blandy committed
332
      sg.sg_ospeed = B9600;
333
      if (ioctl (fd, TIOCGETP, &sg) < 0)
334
	abort ();
Gerd Moellmann's avatar
Gerd Moellmann committed
335
      emacs_ospeed = sg.sg_ospeed;
Jim Blandy's avatar
Jim Blandy committed
336
#endif /* not HAVE_TERMIO */
337
#endif /* not HAVE_TERMIOS */
338
#endif /* not DOS_NT */
Jim Blandy's avatar
Jim Blandy committed
339
    }
340

Gerd Moellmann's avatar
Gerd Moellmann committed
341 342
  baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
	       ? baud_convert[emacs_ospeed] : 9600);
Jim Blandy's avatar
Jim Blandy committed
343 344 345 346
  if (baud_rate == 0)
    baud_rate = 1200;
}

347

Jim Blandy's avatar
Jim Blandy committed
348
/*ARGSUSED*/
Andreas Schwab's avatar
Andreas Schwab committed
349
void
350
set_exclusive_use (int fd)
Jim Blandy's avatar
Jim Blandy committed
351 352 353 354 355 356
{
#ifdef FIOCLEX
  ioctl (fd, FIOCLEX, 0);
#endif
  /* Ok to do nothing if this feature does not exist */
}
357

Jim Blandy's avatar
Jim Blandy committed
358 359

int wait_debugging;   /* Set nonzero to make following function work under dbx
360
			 (at least for bsd).  */
Jim Blandy's avatar
Jim Blandy committed
361 362

SIGTYPE
363
wait_for_termination_signal (void)
Jim Blandy's avatar
Jim Blandy committed
364 365
{}

366
#ifndef MSDOS
Jim Blandy's avatar
Jim Blandy committed
367 368 369
/* Wait for subprocess with process id `pid' to terminate and
   make sure it will get eliminated (not remain forever as a zombie) */

370
void
371
wait_for_termination (int pid)
Jim Blandy's avatar
Jim Blandy committed
372 373 374
{
  while (1)
    {
Dan Nicolaescu's avatar
Dan Nicolaescu committed
375
#if defined (BSD_SYSTEM) || defined (HPUX)
376 377 378 379 380 381 382 383 384
      /* Note that kill returns -1 even if the process is just a zombie now.
	 But inevitably a SIGCHLD interrupt should be generated
	 and child_sig will do wait3 and make the process go away. */
      /* There is some indication that there is a bug involved with
	 termination of subprocesses, perhaps involving a kernel bug too,
	 but no idea what it is.  Just as a hunch we signal SIGCHLD to see
	 if that causes the problem to go away or get worse.  */
      sigsetmask (sigmask (SIGCHLD));
      if (0 > kill (pid, 0))
385
	{
386 387 388 389 390 391 392 393
	  sigsetmask (SIGEMPTYMASK);
	  kill (getpid (), SIGCHLD);
	  break;
	}
      if (wait_debugging)
	sleep (1);
      else
	sigpause (SIGEMPTYMASK);
394
#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
395 396 397 398
#ifdef WINDOWSNT
      wait (0);
      break;
#else /* not WINDOWSNT */
399
      sigblock (sigmask (SIGCHLD));
400 401
      errno = 0;
      if (kill (pid, 0) == -1 && errno == ESRCH)
402 403 404 405
	{
	  sigunblock (sigmask (SIGCHLD));
	  break;
	}
406

407
      sigsuspend (&empty_mask);
408
#endif /* not WINDOWSNT */
409
#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
Jim Blandy's avatar
Jim Blandy committed
410 411 412 413 414 415 416
    }
}

/*
 *	flush any pending output
 *      (may flush input as well; it does not matter the way we use it)
 */
417

418
void
419
flush_pending_output (int channel)
Jim Blandy's avatar
Jim Blandy committed
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
{
#ifdef HAVE_TERMIOS
  /* If we try this, we get hit with SIGTTIN, because
     the child's tty belongs to the child's pgrp. */
#else
#ifdef TCFLSH
  ioctl (channel, TCFLSH, 1);
#else
#ifdef TIOCFLUSH
  int zero = 0;
  /* 3rd arg should be ignored
     but some 4.2 kernels actually want the address of an int
     and nonzero means something different.  */
  ioctl (channel, TIOCFLUSH, &zero);
#endif
#endif
#endif
}
438

Jim Blandy's avatar
Jim Blandy committed
439 440 441 442 443
/*  Set up the terminal at the other end of a pseudo-terminal that
    we will be controlling an inferior through.
    It should not echo or do line-editing, since that is done
    in Emacs.  No padding needed for insertion into an Emacs buffer.  */

444
void
445
child_setup_tty (int out)
Jim Blandy's avatar
Jim Blandy committed
446
{
447
#ifndef WINDOWSNT
Jim Blandy's avatar
Jim Blandy committed
448 449 450
  struct emacs_tty s;

  EMACS_GET_TTY (out, &s);
Jim Blandy's avatar
Jim Blandy committed
451

452
#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
Jim Blandy's avatar
Jim Blandy committed
453 454
  s.main.c_oflag |= OPOST;	/* Enable output postprocessing */
  s.main.c_oflag &= ~ONLCR;	/* Disable map of NL to CR-NL on output */
455
#ifdef NLDLY
456 457 458
  /* http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00406.html
     Some versions of GNU Hurd do not have FFDLY?  */
#ifdef FFDLY
Jim Blandy's avatar
Jim Blandy committed
459 460
  s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
  				/* No output delays */
461 462 463 464
#else
  s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
  				/* No output delays */
#endif
465
#endif
Jim Blandy's avatar
Jim Blandy committed
466 467
  s.main.c_lflag &= ~ECHO;	/* Disable echo */
  s.main.c_lflag |= ISIG;	/* Enable signals */
468 469 470
#ifdef IUCLC
  s.main.c_iflag &= ~IUCLC;	/* Disable downcasing on input.  */
#endif
471 472 473
#ifdef ISTRIP
  s.main.c_iflag &= ~ISTRIP;	/* don't strip 8th bit on input */
#endif
474
#ifdef OLCUC
475 476
  s.main.c_oflag &= ~OLCUC;	/* Disable upcasing on output.  */
#endif
477
  s.main.c_oflag &= ~TAB3;	/* Disable tab expansion */
478
  s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
479 480
  s.main.c_cc[VERASE] = CDISABLE;	/* disable erase processing */
  s.main.c_cc[VKILL] = CDISABLE;	/* disable kill processing */
Jim Blandy's avatar
Jim Blandy committed
481

Jim Blandy's avatar
Jim Blandy committed
482
#ifdef HPUX
Jim Blandy's avatar
Jim Blandy committed
483
  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
Jim Blandy's avatar
Jim Blandy committed
484
#endif /* HPUX */
Jim Blandy's avatar
Jim Blandy committed
485

486 487 488
#ifdef SIGNALS_VIA_CHARACTERS
  /* the QUIT and INTR character are used in process_send_signal
     so set them here to something useful.  */
489
  if (s.main.c_cc[VQUIT] == CDISABLE)
490
    s.main.c_cc[VQUIT] = '\\'&037;	/* Control-\ */
491
  if (s.main.c_cc[VINTR] == CDISABLE)
492 493 494
    s.main.c_cc[VINTR] = 'C'&037;	/* Control-C */
#endif /* not SIGNALS_VIA_CHARACTERS */

Jim Blandy's avatar
Jim Blandy committed
495 496 497
#ifdef AIX
  /* Also, PTY overloads NUL and BREAK.
     don't ignore break, but don't signal either, so it looks like NUL.  */
Jim Blandy's avatar
Jim Blandy committed
498 499
  s.main.c_iflag &= ~IGNBRK;
  s.main.c_iflag &= ~BRKINT;
500 501 502
  /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
     unconditionally.  Then a SIGNALS_VIA_CHARACTERS conditional
     would force it to 0377.  That looks like duplicated code.  */
Jim Blandy's avatar
Jim Blandy committed
503
  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
Jim Blandy's avatar
Jim Blandy committed
504 505
#endif /* AIX */

506 507 508 509 510 511 512 513 514 515 516 517
  /* We used to enable ICANON (and set VEOF to 04), but this leads to
     problems where process.c wants to send EOFs every once in a while
     to force the output, which leads to weird effects when the
     subprocess has disabled ICANON and ends up seeing those spurious
     extra EOFs.  So we don't send EOFs any more in
     process.c:send_process, and instead we disable ICANON by default,
     so if a subsprocess sets up ICANON, it's his problem (or the Elisp
     package that talks to it) to deal with lines that are too long.  */
  s.main.c_lflag &= ~ICANON;	/* Disable line editing and eof processing */
  s.main.c_cc[VMIN] = 1;
  s.main.c_cc[VTIME] = 0;

518 519 520 521 522 523 524 525 526
#else /* not HAVE_TERMIO */

  s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
		       | CBREAK | TANDEM);
  s.main.sg_flags |= LPASS8;
  s.main.sg_erase = 0377;
  s.main.sg_kill = 0377;
  s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */

Jim Blandy's avatar
Jim Blandy committed
527 528
#endif /* not HAVE_TERMIO */

Jim Blandy's avatar
Jim Blandy committed
529
  EMACS_SET_TTY (out, &s, 0);
Jim Blandy's avatar
Jim Blandy committed
530

531
#endif /* not WINDOWSNT */
Jim Blandy's avatar
Jim Blandy committed
532
}
533
#endif	/* MSDOS */
Jim Blandy's avatar
Jim Blandy committed
534

535

Jim Blandy's avatar
Jim Blandy committed
536 537 538 539
/* Record a signal code and the handler for it.  */
struct save_signal
{
  int code;
540
  SIGTYPE (*handler) (int);
Jim Blandy's avatar
Jim Blandy committed
541 542
};

543 544
static void save_signal_handlers (struct save_signal *);
static void restore_signal_handlers (struct save_signal *);
Andreas Schwab's avatar
Andreas Schwab committed
545

Jim Blandy's avatar
Jim Blandy committed
546 547
/* Suspend the Emacs process; give terminal to its superior.  */

548
void
549
sys_suspend (void)
Jim Blandy's avatar
Jim Blandy committed
550
{
551
#if defined (SIGTSTP) && !defined (MSDOS)
Jim Blandy's avatar
Jim Blandy committed
552

553
  {
554
    int pgrp = EMACS_GETPGRP (0);
555 556
    EMACS_KILLPG (pgrp, SIGTSTP);
  }
Jim Blandy's avatar
Jim Blandy committed
557 558 559 560 561

#else /* No SIGTSTP */
/* On a system where suspending is not implemented,
   instead fork a subshell and let it talk directly to the terminal
   while we wait.  */
562 563 564 565 566 567 568
  sys_subshell ();

#endif /* no SIGTSTP */
}

/* Fork a subshell.  */

569
void
570
sys_subshell (void)
571
{
572
#ifdef DOS_NT	/* Demacs 1.1.2 91/10/20 Manabu Higashida */
573 574 575
  int st;
  char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
#endif
576
  int pid;
Jim Blandy's avatar
Jim Blandy committed
577
  struct save_signal saved_handlers[5];
578 579 580
  Lisp_Object dir;
  unsigned char *str = 0;
  int len;
Jim Blandy's avatar
Jim Blandy committed
581 582 583 584 585 586 587 588 589 590 591

  saved_handlers[0].code = SIGINT;
  saved_handlers[1].code = SIGQUIT;
  saved_handlers[2].code = SIGTERM;
#ifdef SIGIO
  saved_handlers[3].code = SIGIO;
  saved_handlers[4].code = 0;
#else
  saved_handlers[3].code = 0;
#endif

592 593 594 595
  /* Mentioning current_buffer->buffer would mean including buffer.h,
     which somehow wedges the hp compiler.  So instead...  */

  dir = intern ("default-directory");
596
  if (NILP (Fboundp (dir)))
597 598
    goto xyzzy;
  dir = Fsymbol_value (dir);
599
  if (!STRINGP (dir))
600 601 602
    goto xyzzy;

  dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
603 604
  str = (unsigned char *) alloca (SCHARS (dir) + 2);
  len = SCHARS (dir);
605
  memcpy (str, SDATA (dir), len);
606 607 608 609
  if (str[len - 1] != '/') str[len++] = '/';
  str[len] = 0;
 xyzzy:

610
#ifdef DOS_NT
611
  pid = 0;
612 613
  save_signal_handlers (saved_handlers);
  synch_process_alive = 1;
614
#else
615
  pid = vfork ();
Jim Blandy's avatar
Jim Blandy committed
616 617
  if (pid == -1)
    error ("Can't spawn subshell");
618 619
#endif

Jim Blandy's avatar
Jim Blandy committed
620 621
  if (pid == 0)
    {
622
      char *sh = 0;
Jim Blandy's avatar
Jim Blandy committed
623

624
#ifdef DOS_NT    /* MW, Aug 1993 */
625
      getwd (oldwd);
626 627
      if (sh == 0)
	sh = (char *) egetenv ("SUSPEND");	/* KFS, 1994-12-14 */
628
#endif
629 630
      if (sh == 0)
	sh = (char *) egetenv ("SHELL");
Jim Blandy's avatar
Jim Blandy committed
631 632
      if (sh == 0)
	sh = "sh";
633

Jim Blandy's avatar
Jim Blandy committed
634
      /* Use our buffer's default directory for the subshell.  */
635
      if (str)
636
	chdir ((char *) str);
637

Jim Blandy's avatar
Jim Blandy committed
638
      close_process_descs ();	/* Close Emacs's pipes/ptys */
639

640
#ifdef SET_EMACS_PRIORITY
641
      {
642
	extern EMACS_INT emacs_priority;
643

644
	if (emacs_priority < 0)
645 646 647 648
	  nice (-emacs_priority);
      }
#endif

649
#ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
650
      {
651 652
	char *epwd = getenv ("PWD");
	char old_pwd[MAXPATHLEN+1+4];
653 654

	/* If PWD is set, pass it with corrected value.  */
655
	if (epwd)
656
	  {
657
	    strcpy (old_pwd, epwd);
658 659 660 661 662 663
	    if (str[len - 1] == '/')
	      str[len - 1] = '\0';
	    setenv ("PWD", str, 1);
	  }
	st = system (sh);
	chdir (oldwd);
664
	if (epwd)
665 666
	  putenv (old_pwd);	/* restore previous value */
      }
667
#else /* not MSDOS */
668 669 670
#ifdef  WINDOWSNT
      /* Waits for process completion */
      pid = _spawnlp (_P_WAIT, sh, sh, NULL);
671
      chdir (oldwd);
672 673 674
      if (pid == -1)
	write (1, "Can't execute subshell", 22);
#else   /* not WINDOWSNT */
675
      execlp (sh, sh, (char *) 0);
Jim Blandy's avatar
Jim Blandy committed
676 677
      write (1, "Can't execute subshell", 22);
      _exit (1);
678
#endif  /* not WINDOWSNT */
679
#endif /* not MSDOS */
Jim Blandy's avatar
Jim Blandy committed
680 681
    }

682
  /* Do this now if we did not do it before.  */
683
#ifndef MSDOS
Jim Blandy's avatar
Jim Blandy committed
684
  save_signal_handlers (saved_handlers);
685
  synch_process_alive = 1;
686 687
#endif

688
#ifndef DOS_NT
Jim Blandy's avatar
Jim Blandy committed
689
  wait_for_termination (pid);
690
#endif
Jim Blandy's avatar
Jim Blandy committed
691
  restore_signal_handlers (saved_handlers);
692
  synch_process_alive = 0;
Jim Blandy's avatar
Jim Blandy committed
693 694
}

Andreas Schwab's avatar
Andreas Schwab committed
695
static void
696
save_signal_handlers (struct save_signal *saved_handlers)
Jim Blandy's avatar
Jim Blandy committed
697 698 699
{
  while (saved_handlers->code)
    {
Joseph Arceneaux's avatar
Joseph Arceneaux committed
700
      saved_handlers->handler
701
        = (SIGTYPE (*) (int)) signal (saved_handlers->code, SIG_IGN);
Jim Blandy's avatar
Jim Blandy committed
702 703 704 705
      saved_handlers++;
    }
}

Andreas Schwab's avatar
Andreas Schwab committed
706
static void
707
restore_signal_handlers (struct save_signal *saved_handlers)
Jim Blandy's avatar
Jim Blandy committed
708 709 710 711 712 713 714 715
{
  while (saved_handlers->code)
    {
      signal (saved_handlers->code, saved_handlers->handler);
      saved_handlers++;
    }
}

716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
#ifndef SIGIO
/* If SIGIO is broken, don't do anything. */
void
init_sigio (int fd)
{
}

void
reset_sigio (int fd)
{
}

void
request_sigio (void)
{
}

void
unrequest_sigio (void)
{
}

#else
Jim Blandy's avatar
Jim Blandy committed
739 740
#ifdef F_SETFL

741
int old_fcntl_flags[MAXDESC];
Jim Blandy's avatar
Jim Blandy committed
742

743
void
744
init_sigio (int fd)
Jim Blandy's avatar
Jim Blandy committed
745 746
{
#ifdef FASYNC
747 748
  old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
  fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
Jim Blandy's avatar
Jim Blandy committed
749
#endif
750
  interrupts_deferred = 0;
Jim Blandy's avatar
Jim Blandy committed
751 752
}

Andreas Schwab's avatar
Andreas Schwab committed
753
void
754
reset_sigio (int fd)
Jim Blandy's avatar
Jim Blandy committed
755
{
756
#ifdef FASYNC
757
  fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
758
#endif
Jim Blandy's avatar
Jim Blandy committed
759 760
}

761
#ifdef FASYNC		/* F_SETFL does not imply existence of FASYNC */
762
/* XXX Uhm, FASYNC is not used anymore here. */
763
/* XXX Yeah, but you need it for SIGIO, don't you? */
Jim Blandy's avatar
Jim Blandy committed
764

765
void
766
request_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
767
{
768
  if (noninteractive)
769 770
    return;

Jim Blandy's avatar
Jim Blandy committed
771
#ifdef SIGWINCH
Jim Blandy's avatar
Jim Blandy committed
772
  sigunblock (sigmask (SIGWINCH));
Jim Blandy's avatar
Jim Blandy committed
773
#endif
Karoly Lorentey's avatar
Karoly Lorentey committed
774
  sigunblock (sigmask (SIGIO));
Jim Blandy's avatar
Jim Blandy committed
775 776 777 778

  interrupts_deferred = 0;
}

779
void
Karoly Lorentey's avatar
Karoly Lorentey committed
780
unrequest_sigio (void)
781
{
782 783 784 785 786
  if (noninteractive)
    return;

#if 0 /* XXX What's wrong with blocking SIGIO under X?  */
  if (x_display_list)
787
    return;
788
#endif
789

Jim Blandy's avatar
Jim Blandy committed
790
#ifdef SIGWINCH
Jim Blandy's avatar
Jim Blandy committed
791
  sigblock (sigmask (SIGWINCH));
Jim Blandy's avatar
Jim Blandy committed
792
#endif
Karoly Lorentey's avatar
Karoly Lorentey committed
793
  sigblock (sigmask (SIGIO));
Jim Blandy's avatar
Jim Blandy committed
794 795 796 797
  interrupts_deferred = 1;
}

#else /* no FASYNC */
798
#ifndef MSDOS
799

800
void
801
request_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
802
{
803
  if (noninteractive || read_socket_hook)
804 805
    return;

Jim Blandy's avatar
Jim Blandy committed
806 807
  croak ("request_sigio");
}
808

809
void
810
unrequest_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
811
{
812
  if (noninteractive || read_socket_hook)
813 814
    return;

Jim Blandy's avatar
Jim Blandy committed
815 816
  croak ("unrequest_sigio");
}
817 818

#endif /* MSDOS */
Jim Blandy's avatar
Jim Blandy committed
819 820
#endif /* FASYNC */
#endif /* F_SETFL */
821
#endif /* SIGIO */
822 823


824 825 826 827 828 829
/* Getting and setting emacs_tty structures.  */

/* Set *TC to the parameters associated with the terminal FD.
   Return zero if all's well, or -1 if we ran into an error we
   couldn't deal with.  */
int
830
emacs_get_tty (int fd, struct emacs_tty *settings)
831 832 833 834
{
  /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
#ifdef HAVE_TCATTR
  /* We have those nifty POSIX tcmumbleattr functions.  */
835
  memset (&settings->main, 0, sizeof (settings->main));
836 837 838 839 840 841 842 843 844 845
  if (tcgetattr (fd, &settings->main) < 0)
    return -1;

#else
#ifdef HAVE_TERMIO
  /* The SYSV-style interface?  */
  if (ioctl (fd, TCGETA, &settings->main) < 0)
    return -1;

#else
846
#ifndef DOS_NT
847 848 849
  /* I give up - I hope you have the BSD ioctls.  */
  if (ioctl (fd, TIOCGETP, &settings->main) < 0)
    return -1;
850
#endif /* not DOS_NT */
851 852 853