sysdep.c 80.8 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Interfaces to system-dependent kernel and library entries.
2
   Copyright (C) 1985-1988, 1993-1995, 1999-2012
Glenn Morris's avatar
Glenn Morris committed
3
                 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
4 5 6

This file is part of GNU Emacs.

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

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
18
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Jim Blandy's avatar
Jim Blandy committed
19

Pavel Janík's avatar
Pavel Janík committed
20
#include <config.h>
21 22 23

#define SYSTIME_INLINE EXTERN_INLINE

24
#include <execinfo.h>
25
#include <stdio.h>
Jim Blandy's avatar
Jim Blandy committed
26
#include <setjmp.h>
27 28 29 30 31
#ifdef HAVE_PWD_H
#include <pwd.h>
#include <grp.h>
#endif /* HAVE_PWD_H */
#include <limits.h>
32
#include <unistd.h>
Dan Nicolaescu's avatar
Dan Nicolaescu committed
33

34
#include <allocator.h>
35
#include <c-ctype.h>
36
#include <careadlinkat.h>
37
#include <ignore-value.h>
38
#include <utimens.h>
39

Jim Blandy's avatar
Jim Blandy committed
40
#include "lisp.h"
41
#include "sysselect.h"
42
#include "blockinput.h"
Jim Blandy's avatar
Jim Blandy committed
43

Paul Eggert's avatar
Paul Eggert committed
44 45
#ifdef BSD_SYSTEM
#include <sys/param.h>
46
#include <sys/sysctl.h>
Paul Eggert's avatar
Paul Eggert committed
47 48 49
#endif

#ifdef __FreeBSD__
50
#include <sys/user.h>
51
#include <sys/resource.h>
52 53 54
#include <math.h>
#endif

55
#ifdef WINDOWSNT
56 57
#define read sys_read
#define write sys_write
58 59 60
#include <windows.h>
#endif /* not WINDOWSNT */

Jim Blandy's avatar
Jim Blandy committed
61 62 63 64
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

65 66 67 68 69
/* Get SI_SRPC_DOMAIN, if it is available.  */
#ifdef HAVE_SYS_SYSTEMINFO_H
#include <sys/systeminfo.h>
#endif

70 71 72
#ifdef MSDOS	/* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
#include "msdos.h"
#include <sys/param.h>
73
#endif
74

75 76
#include <sys/file.h>
#include <fcntl.h>
Jim Blandy's avatar
Jim Blandy committed
77

78
#include "systty.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
79
#include "syswait.h"
Jim Blandy's avatar
Jim Blandy committed
80

Dan Nicolaescu's avatar
Dan Nicolaescu committed
81
#ifdef HAVE_SYS_UTSNAME_H
Jim Blandy's avatar
Jim Blandy committed
82 83
#include <sys/utsname.h>
#include <memory.h>
Dan Nicolaescu's avatar
Dan Nicolaescu committed
84
#endif /* HAVE_SYS_UTSNAME_H */
Jim Blandy's avatar
Jim Blandy committed
85

86
#include "keyboard.h"
Jim Blandy's avatar
Jim Blandy committed
87
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
88 89 90 91 92 93
#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
94
#include "cm.h"  /* for reset_sys_modes */
Jim Blandy's avatar
Jim Blandy committed
95

96 97 98 99
#ifdef WINDOWSNT
#include <direct.h>
/* In process.h which conflicts with the local copy.  */
#define _P_WAIT 0
100 101
int _cdecl _spawnlp (int, const char *, const char *, ...);
int _cdecl _getpid (void);
102
extern char *getwd (char *);
103 104
#endif

Jim Blandy's avatar
Jim Blandy committed
105 106
#include "syssignal.h"
#include "systime.h"
Jim Blandy's avatar
Jim Blandy committed
107

108 109 110
static int emacs_get_tty (int, struct emacs_tty *);
static int emacs_set_tty (int, struct emacs_tty *, int);

111 112 113 114 115
/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781.  */
#ifndef ULLONG_MAX
#define ULLONG_MAX TYPE_MAXIMUM (unsigned long long int)
#endif

Dan Nicolaescu's avatar
Dan Nicolaescu committed
116 117 118
/* Declare here, including term.h is problematic on some systems.  */
extern void tputs (const char *, int, int (*)(int));

119
static const int baud_convert[] =
Jim Blandy's avatar
Jim Blandy committed
120 121 122 123 124
  {
    0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
    1800, 2400, 4800, 9600, 19200, 38400
  };

125

126
#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
127

128
/* Return the current working directory.  Returns NULL on errors.
129 130 131
   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*
132
get_current_dir_name (void)
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
{
  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
      )
    {
151
      buf = malloc (strlen (pwd) + 1);
152 153 154 155 156 157 158 159
      if (!buf)
        return NULL;
      strcpy (buf, pwd);
    }
#ifdef HAVE_GETCWD
  else
    {
      size_t buf_size = 1024;
160
      buf = malloc (buf_size);
161 162 163 164 165 166 167 168 169 170 171 172 173 174
      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;
175
          buf = realloc (buf, buf_size);
176 177 178 179 180 181 182 183
          if (!buf)
            return NULL;
        }
    }
#else
  else
    {
      /* We need MAXPATHLEN here.  */
184
      buf = malloc (MAXPATHLEN + 1);
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
      if (!buf)
        return NULL;
      if (getwd (buf) == NULL)
        {
          int tmp_errno = errno;
          free (buf);
          errno = tmp_errno;
          return NULL;
        }
    }
#endif
  return buf;
}
#endif

200

201
/* Discard pending input on all input descriptors.  */
Jim Blandy's avatar
Jim Blandy committed
202

203
void
204
discard_tty_input (void)
Jim Blandy's avatar
Jim Blandy committed
205
{
206
#ifndef WINDOWSNT
Jim Blandy's avatar
Jim Blandy committed
207
  struct emacs_tty buf;
Jim Blandy's avatar
Jim Blandy committed
208 209 210 211

  if (noninteractive)
    return;

212
#ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
213
  while (dos_keyread () != -1)
214
    ;
215
#else /* not MSDOS */
216
  {
217
    struct tty_display_info *tty;
218 219
    for (tty = tty_list; tty; tty = tty->next)
      {
220 221
        if (tty->input)         /* Is the device suspended? */
          {
Dan Nicolaescu's avatar
Dan Nicolaescu committed
222 223
            emacs_get_tty (fileno (tty->input), &buf);
            emacs_set_tty (fileno (tty->input), &buf, 0);
224
          }
225 226
      }
  }
227
#endif /* not MSDOS */
228
#endif /* not WINDOWSNT */
Jim Blandy's avatar
Jim Blandy committed
229 230
}

231

Jim Blandy's avatar
Jim Blandy committed
232 233
#ifdef SIGTSTP

234
/* Arrange for character C to be read as the next input from
235 236 237
   the terminal.
   XXX What if we have multiple ttys?
*/
238

Andreas Schwab's avatar
Andreas Schwab committed
239
void
240
stuff_char (char c)
Jim Blandy's avatar
Jim Blandy committed
241
{
242
  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
243 244
    return;

Jim Blandy's avatar
Jim Blandy committed
245 246
/* Should perhaps error if in batch mode */
#ifdef TIOCSTI
247
  ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
Jim Blandy's avatar
Jim Blandy committed
248
#else /* no TIOCSTI */
249
  error ("Cannot stuff terminal input characters in this version of Unix");
Jim Blandy's avatar
Jim Blandy committed
250 251 252 253
#endif /* no TIOCSTI */
}

#endif /* SIGTSTP */
254

255
void
256
init_baud_rate (int fd)
Jim Blandy's avatar
Jim Blandy committed
257
{
Dan Nicolaescu's avatar
Dan Nicolaescu committed
258
  int emacs_ospeed;
259

Jim Blandy's avatar
Jim Blandy committed
260
  if (noninteractive)
Gerd Moellmann's avatar
Gerd Moellmann committed
261
    emacs_ospeed = 0;
Jim Blandy's avatar
Jim Blandy committed
262 263
  else
    {
264
#ifdef DOS_NT
Gerd Moellmann's avatar
Gerd Moellmann committed
265
    emacs_ospeed = 15;
266
#else  /* not DOS_NT */
267
      struct termios sg;
Jim Blandy's avatar
Jim Blandy committed
268

269
      sg.c_cflag = B9600;
270
      tcgetattr (fd, &sg);
Gerd Moellmann's avatar
Gerd Moellmann committed
271
      emacs_ospeed = cfgetospeed (&sg);
272
#endif /* not DOS_NT */
Jim Blandy's avatar
Jim Blandy committed
273
    }
274

Gerd Moellmann's avatar
Gerd Moellmann committed
275 276
  baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
	       ? baud_convert[emacs_ospeed] : 9600);
Jim Blandy's avatar
Jim Blandy committed
277 278 279 280
  if (baud_rate == 0)
    baud_rate = 1200;
}

281

Jim Blandy's avatar
Jim Blandy committed
282

283 284 285
/* Set nonzero to make following function work under dbx
   (at least for bsd).  */
int wait_debugging EXTERNALLY_VISIBLE;
Jim Blandy's avatar
Jim Blandy committed
286

287
#ifndef MSDOS
Jim Blandy's avatar
Jim Blandy committed
288

289
static void
290
wait_for_termination_1 (pid_t pid, int interruptible)
Jim Blandy's avatar
Jim Blandy committed
291 292 293
{
  while (1)
    {
Juanma Barranquero's avatar
Juanma Barranquero committed
294
#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined (__GNU__)
295 296
      /* Note that kill returns -1 even if the process is just a zombie now.
	 But inevitably a SIGCHLD interrupt should be generated
Paul Eggert's avatar
Paul Eggert committed
297
	 and child_sig will do waitpid and make the process go away.  */
298 299 300 301
      /* 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.  */
Paul Eggert's avatar
Paul Eggert committed
302 303 304 305 306
      sigset_t sigchild_mask;
      sigemptyset (&sigchild_mask);
      sigaddset (&sigchild_mask, SIGCHLD);
      pthread_sigmask (SIG_SETMASK, &sigchild_mask, 0);

307
      if (0 > kill (pid, 0))
308
	{
Paul Eggert's avatar
Paul Eggert committed
309
	  pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
310 311 312 313 314 315
	  kill (getpid (), SIGCHLD);
	  break;
	}
      if (wait_debugging)
	sleep (1);
      else
Paul Eggert's avatar
Paul Eggert committed
316
	sigsuspend (&empty_mask);
317
#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
318 319 320 321
#ifdef WINDOWSNT
      wait (0);
      break;
#else /* not WINDOWSNT */
Paul Eggert's avatar
Paul Eggert committed
322 323 324 325
      sigset_t blocked;
      sigemptyset (&blocked);
      sigaddset (&blocked, SIGCHLD);
      pthread_sigmask (SIG_BLOCK, &blocked, 0);
326 327
      errno = 0;
      if (kill (pid, 0) == -1 && errno == ESRCH)
328
	{
Paul Eggert's avatar
Paul Eggert committed
329
	  pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
330 331
	  break;
	}
332

333
      sigsuspend (&empty_mask);
334
#endif /* not WINDOWSNT */
335
#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
336 337
      if (interruptible)
	QUIT;
Jim Blandy's avatar
Jim Blandy committed
338 339 340
    }
}

341 342 343 344
/* Wait for subprocess with process id `pid' to terminate and
   make sure it will get eliminated (not remain forever as a zombie) */

void
345
wait_for_termination (pid_t pid)
346 347 348 349 350 351
{
  wait_for_termination_1 (pid, 0);
}

/* Like the above, but allow keyboard interruption. */
void
352
interruptible_wait_for_termination (pid_t pid)
353 354 355 356
{
  wait_for_termination_1 (pid, 1);
}

Jim Blandy's avatar
Jim Blandy committed
357 358 359 360
/*
 *	flush any pending output
 *      (may flush input as well; it does not matter the way we use it)
 */
361

362
void
363
flush_pending_output (int channel)
Jim Blandy's avatar
Jim Blandy committed
364
{
365
  /* FIXME: maybe this function should be removed */
Jim Blandy's avatar
Jim Blandy committed
366
}
367

Jim Blandy's avatar
Jim Blandy committed
368 369 370 371 372
/*  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.  */

373
void
374
child_setup_tty (int out)
Jim Blandy's avatar
Jim Blandy committed
375
{
376
#ifndef WINDOWSNT
Jim Blandy's avatar
Jim Blandy committed
377 378
  struct emacs_tty s;

Dan Nicolaescu's avatar
Dan Nicolaescu committed
379
  emacs_get_tty (out, &s);
Jim Blandy's avatar
Jim Blandy committed
380 381
  s.main.c_oflag |= OPOST;	/* Enable output postprocessing */
  s.main.c_oflag &= ~ONLCR;	/* Disable map of NL to CR-NL on output */
382
#ifdef NLDLY
383 384 385
  /* 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
386 387
  s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
  				/* No output delays */
388 389 390 391
#else
  s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY);
  				/* No output delays */
#endif
392
#endif
Jim Blandy's avatar
Jim Blandy committed
393 394
  s.main.c_lflag &= ~ECHO;	/* Disable echo */
  s.main.c_lflag |= ISIG;	/* Enable signals */
395 396 397
#ifdef IUCLC
  s.main.c_iflag &= ~IUCLC;	/* Disable downcasing on input.  */
#endif
398 399 400
#ifdef ISTRIP
  s.main.c_iflag &= ~ISTRIP;	/* don't strip 8th bit on input */
#endif
401
#ifdef OLCUC
402 403
  s.main.c_oflag &= ~OLCUC;	/* Disable upcasing on output.  */
#endif
404
  s.main.c_oflag &= ~TAB3;	/* Disable tab expansion */
405
  s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
406 407
  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
408

Jim Blandy's avatar
Jim Blandy committed
409
#ifdef HPUX
Jim Blandy's avatar
Jim Blandy committed
410
  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
Jim Blandy's avatar
Jim Blandy committed
411
#endif /* HPUX */
Jim Blandy's avatar
Jim Blandy committed
412

413 414 415
#ifdef SIGNALS_VIA_CHARACTERS
  /* the QUIT and INTR character are used in process_send_signal
     so set them here to something useful.  */
416
  if (s.main.c_cc[VQUIT] == CDISABLE)
417
    s.main.c_cc[VQUIT] = '\\'&037;	/* Control-\ */
418
  if (s.main.c_cc[VINTR] == CDISABLE)
419 420 421
    s.main.c_cc[VINTR] = 'C'&037;	/* Control-C */
#endif /* not SIGNALS_VIA_CHARACTERS */

Jim Blandy's avatar
Jim Blandy committed
422 423 424
#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
425 426
  s.main.c_iflag &= ~IGNBRK;
  s.main.c_iflag &= ~BRKINT;
427 428 429
  /* 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
430
  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
Jim Blandy's avatar
Jim Blandy committed
431 432
#endif /* AIX */

433
  /* We originally enabled ICANON (and set VEOF to 04), and then had
Paul Eggert's avatar
Paul Eggert committed
434
     process.c send additional EOF chars to flush the output when faced
435
     with long lines, but this leads to weird effects when the
436 437
     subprocess has disabled ICANON and ends up seeing those spurious
     extra EOFs.  So we don't send EOFs any more in
438 439 440 441 442 443 444 445 446 447 448
     process.c:send_process.  First we tried to 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.  But this disables some features, such as the ability
     to send EOF signals.  So we re-enabled ICANON but there is no
     more "send eof to flush" going on (which is wrong and unportable
     in itself).  The correct way to handle too much output is to
     buffer what could not be written and then write it again when
     select returns ok for writing.  This has it own set of
     problems.  Write is now asynchronous, is that a problem?  How much
     do we buffer, and what do we do when that limit is reached?  */
449 450 451

  s.main.c_lflag |= ICANON;	/* Enable line editing and eof processing */
  s.main.c_cc[VEOF] = 'D'&037;	/* Control-D */
Nick Roberts's avatar
Nick Roberts committed
452
#if 0	    /* These settings only apply to non-ICANON mode. */
453 454
  s.main.c_cc[VMIN] = 1;
  s.main.c_cc[VTIME] = 0;
455
#endif
456

Dan Nicolaescu's avatar
Dan Nicolaescu committed
457
  emacs_set_tty (out, &s, 0);
458
#endif /* not WINDOWSNT */
Jim Blandy's avatar
Jim Blandy committed
459
}
Dan Nicolaescu's avatar
Dan Nicolaescu committed
460
#endif	/* not MSDOS */
Jim Blandy's avatar
Jim Blandy committed
461

462

Paul Eggert's avatar
Paul Eggert committed
463
/* Record a signal code and the action for it.  */
Jim Blandy's avatar
Jim Blandy committed
464 465 466
struct save_signal
{
  int code;
Paul Eggert's avatar
Paul Eggert committed
467
  struct sigaction action;
Jim Blandy's avatar
Jim Blandy committed
468 469
};

470 471
static void save_signal_handlers (struct save_signal *);
static void restore_signal_handlers (struct save_signal *);
Andreas Schwab's avatar
Andreas Schwab committed
472

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

475
void
476
sys_suspend (void)
Jim Blandy's avatar
Jim Blandy committed
477
{
478
#if defined (SIGTSTP) && !defined (MSDOS)
Jim Blandy's avatar
Jim Blandy committed
479

480
  {
481
    int pgrp = EMACS_GETPGRP (0);
482 483
    EMACS_KILLPG (pgrp, SIGTSTP);
  }
Jim Blandy's avatar
Jim Blandy committed
484 485 486 487 488

#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.  */
489 490 491 492 493 494 495
  sys_subshell ();

#endif /* no SIGTSTP */
}

/* Fork a subshell.  */

496
void
497
sys_subshell (void)
498
{
499
#ifdef DOS_NT	/* Demacs 1.1.2 91/10/20 Manabu Higashida */
500 501 502
  int st;
  char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
#endif
503
  int pid;
Jim Blandy's avatar
Jim Blandy committed
504
  struct save_signal saved_handlers[5];
505
  Lisp_Object dir;
Paul Eggert's avatar
Paul Eggert committed
506
  unsigned char *volatile str_volatile = 0;
507
  unsigned char *str;
508
  int len;
Jim Blandy's avatar
Jim Blandy committed
509 510 511 512

  saved_handlers[0].code = SIGINT;
  saved_handlers[1].code = SIGQUIT;
  saved_handlers[2].code = SIGTERM;
Paul Eggert's avatar
Paul Eggert committed
513
#ifdef USABLE_SIGIO
Jim Blandy's avatar
Jim Blandy committed
514 515 516 517 518 519
  saved_handlers[3].code = SIGIO;
  saved_handlers[4].code = 0;
#else
  saved_handlers[3].code = 0;
#endif

520 521 522 523
  /* Mentioning current_buffer->buffer would mean including buffer.h,
     which somehow wedges the hp compiler.  So instead...  */

  dir = intern ("default-directory");
524
  if (NILP (Fboundp (dir)))
525 526
    goto xyzzy;
  dir = Fsymbol_value (dir);
527
  if (!STRINGP (dir))
528 529 530
    goto xyzzy;

  dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
531
  str_volatile = str = alloca (SCHARS (dir) + 2);
532
  len = SCHARS (dir);
533
  memcpy (str, SDATA (dir), len);
534 535 536 537
  if (str[len - 1] != '/') str[len++] = '/';
  str[len] = 0;
 xyzzy:

538
#ifdef DOS_NT
539
  pid = 0;
540 541
  save_signal_handlers (saved_handlers);
  synch_process_alive = 1;
542
#else
543
  pid = vfork ();
Jim Blandy's avatar
Jim Blandy committed
544 545
  if (pid == -1)
    error ("Can't spawn subshell");
546 547
#endif

Jim Blandy's avatar
Jim Blandy committed
548 549
  if (pid == 0)
    {
550
      const char *sh = 0;
Jim Blandy's avatar
Jim Blandy committed
551

552
#ifdef DOS_NT    /* MW, Aug 1993 */
553
      getwd (oldwd);
554 555
      if (sh == 0)
	sh = (char *) egetenv ("SUSPEND");	/* KFS, 1994-12-14 */
556
#endif
557 558
      if (sh == 0)
	sh = (char *) egetenv ("SHELL");
Jim Blandy's avatar
Jim Blandy committed
559 560
      if (sh == 0)
	sh = "sh";
561

Jim Blandy's avatar
Jim Blandy committed
562
      /* Use our buffer's default directory for the subshell.  */
Paul Eggert's avatar
Paul Eggert committed
563
      str = str_volatile;
Paul Eggert's avatar
Paul Eggert committed
564 565 566 567 568 569 570
      if (str && chdir ((char *) str) != 0)
	{
#ifndef DOS_NT
	  ignore_value (write (1, "Can't chdir\n", 12));
	  _exit (1);
#endif
	}
571

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

574
#ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
575
      {
576 577
	char *epwd = getenv ("PWD");
	char old_pwd[MAXPATHLEN+1+4];
578 579

	/* If PWD is set, pass it with corrected value.  */
580
	if (epwd)
581
	  {
582
	    strcpy (old_pwd, epwd);
583 584 585 586 587
	    if (str[len - 1] == '/')
	      str[len - 1] = '\0';
	    setenv ("PWD", str, 1);
	  }
	st = system (sh);
Paul Eggert's avatar
Paul Eggert committed
588
	chdir (oldwd);	/* FIXME: Do the right thing on chdir failure.  */
589
	if (epwd)
590 591
	  putenv (old_pwd);	/* restore previous value */
      }
592
#else /* not MSDOS */
593 594 595
#ifdef  WINDOWSNT
      /* Waits for process completion */
      pid = _spawnlp (_P_WAIT, sh, sh, NULL);
Paul Eggert's avatar
Paul Eggert committed
596
      chdir (oldwd);	/* FIXME: Do the right thing on chdir failure.  */
597 598 599
      if (pid == -1)
	write (1, "Can't execute subshell", 22);
#else   /* not WINDOWSNT */
600
      execlp (sh, sh, (char *) 0);
601
      ignore_value (write (1, "Can't execute subshell", 22));
Jim Blandy's avatar
Jim Blandy committed
602
      _exit (1);
603
#endif  /* not WINDOWSNT */
604
#endif /* not MSDOS */
Jim Blandy's avatar
Jim Blandy committed
605 606
    }

607
  /* Do this now if we did not do it before.  */
608
#ifndef MSDOS
Jim Blandy's avatar
Jim Blandy committed
609
  save_signal_handlers (saved_handlers);
610
  synch_process_alive = 1;
611 612
#endif

613
#ifndef DOS_NT
Jim Blandy's avatar
Jim Blandy committed
614
  wait_for_termination (pid);
615
#endif
Jim Blandy's avatar
Jim Blandy committed
616
  restore_signal_handlers (saved_handlers);
617
  synch_process_alive = 0;
Jim Blandy's avatar
Jim Blandy committed
618 619
}

Andreas Schwab's avatar
Andreas Schwab committed
620
static void
621
save_signal_handlers (struct save_signal *saved_handlers)
Jim Blandy's avatar
Jim Blandy committed
622 623 624
{
  while (saved_handlers->code)
    {
Paul Eggert's avatar
Paul Eggert committed
625 626 627
      struct sigaction action;
      emacs_sigaction_init (&action, SIG_IGN);
      sigaction (saved_handlers->code, &action, &saved_handlers->action);
Jim Blandy's avatar
Jim Blandy committed
628 629 630 631
      saved_handlers++;
    }
}

Andreas Schwab's avatar
Andreas Schwab committed
632
static void
633
restore_signal_handlers (struct save_signal *saved_handlers)
Jim Blandy's avatar
Jim Blandy committed
634 635 636
{
  while (saved_handlers->code)
    {
Paul Eggert's avatar
Paul Eggert committed
637
      sigaction (saved_handlers->code, &saved_handlers->action, 0);
Jim Blandy's avatar
Jim Blandy committed
638 639 640 641
      saved_handlers++;
    }
}

Paul Eggert's avatar
Paul Eggert committed
642
#ifdef USABLE_SIGIO
643
static int old_fcntl_flags[MAXDESC];
Paul Eggert's avatar
Paul Eggert committed
644
#endif
Jim Blandy's avatar
Jim Blandy committed
645

646
void
647
init_sigio (int fd)
Jim Blandy's avatar
Jim Blandy committed
648
{
Paul Eggert's avatar
Paul Eggert committed
649
#ifdef USABLE_SIGIO
650 651
  old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
  fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
652
  interrupts_deferred = 0;
Paul Eggert's avatar
Paul Eggert committed
653
#endif
Jim Blandy's avatar
Jim Blandy committed
654 655
}

656
static void
657
reset_sigio (int fd)
Jim Blandy's avatar
Jim Blandy committed
658
{
Paul Eggert's avatar
Paul Eggert committed
659
#ifdef USABLE_SIGIO
660
  fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
661
#endif
Jim Blandy's avatar
Jim Blandy committed
662 663
}

664
void
665
request_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
666
{
Paul Eggert's avatar
Paul Eggert committed
667
#ifdef USABLE_SIGIO
Paul Eggert's avatar
Paul Eggert committed
668 669
  sigset_t unblocked;

670
  if (noninteractive)
671 672
    return;

Paul Eggert's avatar
Paul Eggert committed
673
  sigemptyset (&unblocked);
Paul Eggert's avatar
Paul Eggert committed
674
# ifdef SIGWINCH
Paul Eggert's avatar
Paul Eggert committed
675
  sigaddset (&unblocked, SIGWINCH);
Paul Eggert's avatar
Paul Eggert committed
676
# endif
Paul Eggert's avatar
Paul Eggert committed
677 678
  sigaddset (&unblocked, SIGIO);
  pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
Jim Blandy's avatar
Jim Blandy committed
679 680

  interrupts_deferred = 0;
Paul Eggert's avatar
Paul Eggert committed
681
#endif
Jim Blandy's avatar
Jim Blandy committed
682 683
}

684
void
Karoly Lorentey's avatar
Karoly Lorentey committed
685
unrequest_sigio (void)
686
{
Paul Eggert's avatar
Paul Eggert committed
687
#ifdef USABLE_SIGIO
Paul Eggert's avatar
Paul Eggert committed
688 689
  sigset_t blocked;

690 691 692
  if (noninteractive)
    return;

Paul Eggert's avatar
Paul Eggert committed
693
  sigemptyset (&blocked);
Paul Eggert's avatar
Paul Eggert committed
694
# ifdef SIGWINCH
Paul Eggert's avatar
Paul Eggert committed
695
  sigaddset (&blocked, SIGWINCH);
Paul Eggert's avatar
Paul Eggert committed
696
# endif
Paul Eggert's avatar
Paul Eggert committed
697 698
  sigaddset (&blocked, SIGIO);
  pthread_sigmask (SIG_BLOCK, &blocked, 0);
Jim Blandy's avatar
Jim Blandy committed
699
  interrupts_deferred = 1;
Paul Eggert's avatar
Paul Eggert committed
700
#endif
Jim Blandy's avatar
Jim Blandy committed
701
}
702

703
void
Paul Eggert's avatar
Paul Eggert committed
704
ignore_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
705
{
Paul Eggert's avatar
Paul Eggert committed
706 707 708
#ifdef USABLE_SIGIO
  signal (SIGIO, SIG_IGN);
#endif
Jim Blandy's avatar
Jim Blandy committed
709
}
710

711

712 713 714 715 716 717
/* 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
718
emacs_get_tty (int fd, struct emacs_tty *settings)
719 720
{
  /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
Dan Nicolaescu's avatar
Dan Nicolaescu committed
721
#ifndef DOS_NT
722
  /* We have those nifty POSIX tcmumbleattr functions.  */
723
  memset (&settings->main, 0, sizeof (settings->main));
724 725 726 727 728 729 730 731 732 733
  if (tcgetattr (fd, &settings->main) < 0)
    return -1;
#endif

  /* We have survived the tempest.  */
  return 0;
}


/* Set the parameters of the tty on FD according to the contents of
734
   *SETTINGS.  If FLUSHP is non-zero, we discard input.
735
   Return 0 if all went well, and -1 if anything failed.  */
736

737
int
738
emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
739 740
{
  /* Set the primary parameters - baud rate, character size, etcetera.  */
Dan Nicolaescu's avatar
Dan Nicolaescu committed
741
#ifndef DOS_NT
742
  int i;
743 744
  /* We have those nifty POSIX tcmumbleattr functions.
     William J. Smith <wjs@wiis.wang.com> writes:
745
     "POSIX 1003.1 defines tcsetattr to return success if it was
746 747 748 749
     able to perform any of the requested actions, even if some
     of the requested actions could not be performed.
     We must read settings back to ensure tty setup properly.
     AIX requires this to keep tty from hanging occasionally."  */
750
  /* This make sure that we don't loop indefinitely in here.  */
751
  for (i = 0 ; i < 10 ; i++)
752
    if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
753 754 755 756 757 758 759 760 761 762
      {
	if (errno == EINTR)
	  continue;
	else
	  return -1;
      }
    else
      {
	struct termios new;

763
	memset (&new, 0, sizeof (new));
764 765
	/* Get the current settings, and see if they're what we asked for.  */
	tcgetattr (fd, &new);
766 767 768 769 770 771 772 773
	/* We cannot use memcmp on the whole structure here because under
	 * aix386 the termios structure has some reserved field that may
	 * not be filled in.
	 */
	if (   new.c_iflag == settings->main.c_iflag
	    && new.c_oflag == settings->main.c_oflag
	    && new.c_cflag == settings->main.c_cflag
	    && new.c_lflag == settings->main.c_lflag
774
	    && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
775
	  break;
776 777
	else
	  continue;
778 779
      }
#endif
780

781 782 783 784
  /* We have survived the tempest.  */
  return 0;
}

Jim Blandy's avatar
Jim Blandy committed
785 786 787


#ifdef F_SETOWN
788
static int old_fcntl_owner[MAXDESC];
Jim Blandy's avatar
Jim Blandy committed
789 790 791 792 793 794
#endif /* F_SETOWN */

/* This may also be defined in stdio,
   but if so, this does no harm,
   and using the same name avoids wasting the other one's space.  */

795
#if defined (USG)
Jim Blandy's avatar
Jim Blandy committed
796 797 798 799
unsigned char _sobuf[BUFSIZ+8];
#else
char _sobuf[BUFSIZ];
#endif
800