sysdep.c 75.9 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-2011
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
#include <ctype.h>
Jim Blandy's avatar
Jim Blandy committed
22
#include <signal.h>
23
#include <stdio.h>
Jim Blandy's avatar
Jim Blandy committed
24
#include <setjmp.h>
25 26 27 28 29 30 31
#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 */
32
#include <unistd.h>
Dan Nicolaescu's avatar
Dan Nicolaescu committed
33

34 35
#include <ignore-value.h>

Jim Blandy's avatar
Jim Blandy committed
36
#include "lisp.h"
37
#include "sysselect.h"
38
#include "blockinput.h"
Jim Blandy's avatar
Jim Blandy committed
39

40
#ifdef WINDOWSNT
41 42
#define read sys_read
#define write sys_write
43
#include <windows.h>
44 45 46
#ifndef NULL
#define NULL 0
#endif
47 48
#endif /* not WINDOWSNT */

Jim Blandy's avatar
Jim Blandy committed
49 50 51 52
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

53
#ifdef HAVE_SETPGID
Dan Nicolaescu's avatar
Dan Nicolaescu committed
54
#if !defined (USG)
55
#undef setpgrp
56 57
#define setpgrp setpgid
#endif
58
#endif
59

60 61 62 63 64
/* Get SI_SRPC_DOMAIN, if it is available.  */
#ifdef HAVE_SYS_SYSTEMINFO_H
#include <sys/systeminfo.h>
#endif

65 66 67 68 69
#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>
70
#endif
71

72 73
#include <sys/file.h>
#include <fcntl.h>
Jim Blandy's avatar
Jim Blandy committed
74

75
#include "systty.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
76
#include "syswait.h"
Jim Blandy's avatar
Jim Blandy committed
77

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

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

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

Jim Blandy's avatar
Jim Blandy committed
102 103
#include "syssignal.h"
#include "systime.h"
104 105 106 107 108 109 110 111 112 113 114 115 116 117
#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
118

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

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

128
void croak (char *) NO_RETURN;
129

130 131 132 133
/* Temporary used by `sigblock' when defined in terms of signprocmask.  */

SIGMASKTYPE sigprocmask_set;

134

135
#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
136

137
/* Return the current working directory.  Returns NULL on errors.
138 139 140
   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*
141
get_current_dir_name (void)
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
{
  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;
169
      buf = (char *) malloc (buf_size);
170 171 172 173 174 175 176 177 178 179 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 207 208
      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

209

210
/* Discard pending input on all input descriptors.  */
Jim Blandy's avatar
Jim Blandy committed
211

212
void
213
discard_tty_input (void)
Jim Blandy's avatar
Jim Blandy committed
214
{
215
#ifndef WINDOWSNT
Jim Blandy's avatar
Jim Blandy committed
216
  struct emacs_tty buf;
Jim Blandy's avatar
Jim Blandy committed
217 218 219 220

  if (noninteractive)
    return;

221
#ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
222
  while (dos_keyread () != -1)
223
    ;
224
#else /* not MSDOS */
225
  {
226
    struct tty_display_info *tty;
227 228
    for (tty = tty_list; tty; tty = tty->next)
      {
229 230
        if (tty->input)         /* Is the device suspended? */
          {
Dan Nicolaescu's avatar
Dan Nicolaescu committed
231 232
            emacs_get_tty (fileno (tty->input), &buf);
            emacs_set_tty (fileno (tty->input), &buf, 0);
233
          }
234 235
      }
  }
236
#endif /* not MSDOS */
237
#endif /* not WINDOWSNT */
Jim Blandy's avatar
Jim Blandy committed
238 239
}

240

Jim Blandy's avatar
Jim Blandy committed
241 242
#ifdef SIGTSTP

243
/* Arrange for character C to be read as the next input from
244 245 246
   the terminal.
   XXX What if we have multiple ttys?
*/
247

Andreas Schwab's avatar
Andreas Schwab committed
248
void
249
stuff_char (char c)
Jim Blandy's avatar
Jim Blandy committed
250
{
251
  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
252 253
    return;

Jim Blandy's avatar
Jim Blandy committed
254 255
/* Should perhaps error if in batch mode */
#ifdef TIOCSTI
256
  ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
Jim Blandy's avatar
Jim Blandy committed
257
#else /* no TIOCSTI */
258
  error ("Cannot stuff terminal input characters in this version of Unix");
Jim Blandy's avatar
Jim Blandy committed
259 260 261 262
#endif /* no TIOCSTI */
}

#endif /* SIGTSTP */
263

264
void
265
init_baud_rate (int fd)
Jim Blandy's avatar
Jim Blandy committed
266
{
Dan Nicolaescu's avatar
Dan Nicolaescu committed
267
  int emacs_ospeed;
268

Jim Blandy's avatar
Jim Blandy committed
269
  if (noninteractive)
Gerd Moellmann's avatar
Gerd Moellmann committed
270
    emacs_ospeed = 0;
Jim Blandy's avatar
Jim Blandy committed
271 272
  else
    {
273
#ifdef DOS_NT
Gerd Moellmann's avatar
Gerd Moellmann committed
274
    emacs_ospeed = 15;
275
#else  /* not DOS_NT */
276
      struct termios sg;
Jim Blandy's avatar
Jim Blandy committed
277

278
      sg.c_cflag = B9600;
279
      tcgetattr (fd, &sg);
Gerd Moellmann's avatar
Gerd Moellmann committed
280
      emacs_ospeed = cfgetospeed (&sg);
281
#endif /* not DOS_NT */
Jim Blandy's avatar
Jim Blandy committed
282
    }
283

Gerd Moellmann's avatar
Gerd Moellmann committed
284 285
  baud_rate = (emacs_ospeed < sizeof baud_convert / sizeof baud_convert[0]
	       ? baud_convert[emacs_ospeed] : 9600);
Jim Blandy's avatar
Jim Blandy committed
286 287 288 289
  if (baud_rate == 0)
    baud_rate = 1200;
}

290

Jim Blandy's avatar
Jim Blandy committed
291 292

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

SIGTYPE
296
wait_for_termination_signal (void)
Jim Blandy's avatar
Jim Blandy committed
297 298
{}

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

303
void
304
wait_for_termination (int pid)
Jim Blandy's avatar
Jim Blandy committed
305 306 307
{
  while (1)
    {
Dan Nicolaescu's avatar
Dan Nicolaescu committed
308
#if defined (BSD_SYSTEM) || defined (HPUX)
309 310 311 312 313 314 315 316 317
      /* 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))
318
	{
319 320 321 322 323 324 325 326
	  sigsetmask (SIGEMPTYMASK);
	  kill (getpid (), SIGCHLD);
	  break;
	}
      if (wait_debugging)
	sleep (1);
      else
	sigpause (SIGEMPTYMASK);
327
#else /* not BSD_SYSTEM, and not HPUX version >= 6 */
328 329 330 331
#ifdef WINDOWSNT
      wait (0);
      break;
#else /* not WINDOWSNT */
332
      sigblock (sigmask (SIGCHLD));
333 334
      errno = 0;
      if (kill (pid, 0) == -1 && errno == ESRCH)
335 336 337 338
	{
	  sigunblock (sigmask (SIGCHLD));
	  break;
	}
339

340
      sigsuspend (&empty_mask);
341
#endif /* not WINDOWSNT */
342
#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
Jim Blandy's avatar
Jim Blandy committed
343 344 345 346 347 348 349
    }
}

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

351
void
352
flush_pending_output (int channel)
Jim Blandy's avatar
Jim Blandy committed
353
{
354
  /* FIXME: maybe this function should be removed */
Jim Blandy's avatar
Jim Blandy committed
355
}
356

Jim Blandy's avatar
Jim Blandy committed
357 358 359 360 361
/*  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.  */

362
void
363
child_setup_tty (int out)
Jim Blandy's avatar
Jim Blandy committed
364
{
365
#ifndef WINDOWSNT
Jim Blandy's avatar
Jim Blandy committed
366 367
  struct emacs_tty s;

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

Jim Blandy's avatar
Jim Blandy committed
398
#ifdef HPUX
Jim Blandy's avatar
Jim Blandy committed
399
  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
Jim Blandy's avatar
Jim Blandy committed
400
#endif /* HPUX */
Jim Blandy's avatar
Jim Blandy committed
401

402 403 404
#ifdef SIGNALS_VIA_CHARACTERS
  /* the QUIT and INTR character are used in process_send_signal
     so set them here to something useful.  */
405
  if (s.main.c_cc[VQUIT] == CDISABLE)
406
    s.main.c_cc[VQUIT] = '\\'&037;	/* Control-\ */
407
  if (s.main.c_cc[VINTR] == CDISABLE)
408 409 410
    s.main.c_cc[VINTR] = 'C'&037;	/* Control-C */
#endif /* not SIGNALS_VIA_CHARACTERS */

Jim Blandy's avatar
Jim Blandy committed
411 412 413
#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
414 415
  s.main.c_iflag &= ~IGNBRK;
  s.main.c_iflag &= ~BRKINT;
416 417 418
  /* 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
419
  s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
Jim Blandy's avatar
Jim Blandy committed
420 421
#endif /* AIX */

422 423 424
  /* We originally enabled ICANON (and set VEOF to 04), and then had
     proces.c send additional EOF chars to flush the output when faced
     with long lines, but this leads to weird effects when the
425 426
     subprocess has disabled ICANON and ends up seeing those spurious
     extra EOFs.  So we don't send EOFs any more in
427 428 429 430 431 432 433 434 435 436 437
     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?  */
438 439 440

  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
441
#if 0	    /* These settings only apply to non-ICANON mode. */
442 443
  s.main.c_cc[VMIN] = 1;
  s.main.c_cc[VTIME] = 0;
444
#endif
445

Dan Nicolaescu's avatar
Dan Nicolaescu committed
446
  emacs_set_tty (out, &s, 0);
447
#endif /* not WINDOWSNT */
Jim Blandy's avatar
Jim Blandy committed
448
}
Dan Nicolaescu's avatar
Dan Nicolaescu committed
449
#endif	/* not MSDOS */
Jim Blandy's avatar
Jim Blandy committed
450

451

Jim Blandy's avatar
Jim Blandy committed
452 453 454 455
/* Record a signal code and the handler for it.  */
struct save_signal
{
  int code;
456
  SIGTYPE (*handler) (int);
Jim Blandy's avatar
Jim Blandy committed
457 458
};

459 460
static void save_signal_handlers (struct save_signal *);
static void restore_signal_handlers (struct save_signal *);
Andreas Schwab's avatar
Andreas Schwab committed
461

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

464
void
465
sys_suspend (void)
Jim Blandy's avatar
Jim Blandy committed
466
{
467
#if defined (SIGTSTP) && !defined (MSDOS)
Jim Blandy's avatar
Jim Blandy committed
468

469
  {
470
    int pgrp = EMACS_GETPGRP (0);
471 472
    EMACS_KILLPG (pgrp, SIGTSTP);
  }
Jim Blandy's avatar
Jim Blandy committed
473 474 475 476 477

#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.  */
478 479 480 481 482 483 484
  sys_subshell ();

#endif /* no SIGTSTP */
}

/* Fork a subshell.  */

485
void
486
sys_subshell (void)
487
{
488
#ifdef DOS_NT	/* Demacs 1.1.2 91/10/20 Manabu Higashida */
489 490 491
  int st;
  char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
#endif
492
  int pid;
Jim Blandy's avatar
Jim Blandy committed
493
  struct save_signal saved_handlers[5];
494 495 496
  Lisp_Object dir;
  unsigned char *str = 0;
  int len;
Jim Blandy's avatar
Jim Blandy committed
497 498 499 500 501 502 503 504 505 506 507

  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

508 509 510 511
  /* Mentioning current_buffer->buffer would mean including buffer.h,
     which somehow wedges the hp compiler.  So instead...  */

  dir = intern ("default-directory");
512
  if (NILP (Fboundp (dir)))
513 514
    goto xyzzy;
  dir = Fsymbol_value (dir);
515
  if (!STRINGP (dir))
516 517 518
    goto xyzzy;

  dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
519 520
  str = (unsigned char *) alloca (SCHARS (dir) + 2);
  len = SCHARS (dir);
521
  memcpy (str, SDATA (dir), len);
522 523 524 525
  if (str[len - 1] != '/') str[len++] = '/';
  str[len] = 0;
 xyzzy:

526
#ifdef DOS_NT
527
  pid = 0;
528 529
  save_signal_handlers (saved_handlers);
  synch_process_alive = 1;
530
#else
531
  pid = vfork ();
Jim Blandy's avatar
Jim Blandy committed
532 533
  if (pid == -1)
    error ("Can't spawn subshell");
534 535
#endif

Jim Blandy's avatar
Jim Blandy committed
536 537
  if (pid == 0)
    {
538
      const char *sh = 0;
Jim Blandy's avatar
Jim Blandy committed
539

540
#ifdef DOS_NT    /* MW, Aug 1993 */
541
      getwd (oldwd);
542 543
      if (sh == 0)
	sh = (char *) egetenv ("SUSPEND");	/* KFS, 1994-12-14 */
544
#endif
545 546
      if (sh == 0)
	sh = (char *) egetenv ("SHELL");
Jim Blandy's avatar
Jim Blandy committed
547 548
      if (sh == 0)
	sh = "sh";
549

Jim Blandy's avatar
Jim Blandy committed
550
      /* Use our buffer's default directory for the subshell.  */
Paul Eggert's avatar
Paul Eggert committed
551 552 553 554 555 556 557
      if (str && chdir ((char *) str) != 0)
	{
#ifndef DOS_NT
	  ignore_value (write (1, "Can't chdir\n", 12));
	  _exit (1);
#endif
	}
558

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

561
#ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
562
      {
563 564
	char *epwd = getenv ("PWD");
	char old_pwd[MAXPATHLEN+1+4];
565 566

	/* If PWD is set, pass it with corrected value.  */
567
	if (epwd)
568
	  {
569
	    strcpy (old_pwd, epwd);
570 571 572 573 574
	    if (str[len - 1] == '/')
	      str[len - 1] = '\0';
	    setenv ("PWD", str, 1);
	  }
	st = system (sh);
Paul Eggert's avatar
Paul Eggert committed
575
	chdir (oldwd);	/* FIXME: Do the right thing on chdir failure.  */
576
	if (epwd)
577 578
	  putenv (old_pwd);	/* restore previous value */
      }
579
#else /* not MSDOS */
580 581 582
#ifdef  WINDOWSNT
      /* Waits for process completion */
      pid = _spawnlp (_P_WAIT, sh, sh, NULL);
Paul Eggert's avatar
Paul Eggert committed
583
      chdir (oldwd);	/* FIXME: Do the right thing on chdir failure.  */
584 585 586
      if (pid == -1)
	write (1, "Can't execute subshell", 22);
#else   /* not WINDOWSNT */
587
      execlp (sh, sh, (char *) 0);
588
      ignore_value (write (1, "Can't execute subshell", 22));
Jim Blandy's avatar
Jim Blandy committed
589
      _exit (1);
590
#endif  /* not WINDOWSNT */
591
#endif /* not MSDOS */
Jim Blandy's avatar
Jim Blandy committed
592 593
    }

594
  /* Do this now if we did not do it before.  */
595
#ifndef MSDOS
Jim Blandy's avatar
Jim Blandy committed
596
  save_signal_handlers (saved_handlers);
597
  synch_process_alive = 1;
598 599
#endif

600
#ifndef DOS_NT
Jim Blandy's avatar
Jim Blandy committed
601
  wait_for_termination (pid);
602
#endif
Jim Blandy's avatar
Jim Blandy committed
603
  restore_signal_handlers (saved_handlers);
604
  synch_process_alive = 0;
Jim Blandy's avatar
Jim Blandy committed
605 606
}

Andreas Schwab's avatar
Andreas Schwab committed
607
static void
608
save_signal_handlers (struct save_signal *saved_handlers)
Jim Blandy's avatar
Jim Blandy committed
609 610 611
{
  while (saved_handlers->code)
    {
Joseph Arceneaux's avatar
Joseph Arceneaux committed
612
      saved_handlers->handler
613
        = (SIGTYPE (*) (int)) signal (saved_handlers->code, SIG_IGN);
Jim Blandy's avatar
Jim Blandy committed
614 615 616 617
      saved_handlers++;
    }
}

Andreas Schwab's avatar
Andreas Schwab committed
618
static void
619
restore_signal_handlers (struct save_signal *saved_handlers)
Jim Blandy's avatar
Jim Blandy committed
620 621 622 623 624 625 626 627
{
  while (saved_handlers->code)
    {
      signal (saved_handlers->code, saved_handlers->handler);
      saved_handlers++;
    }
}

628 629 630 631 632 633 634
#ifndef SIGIO
/* If SIGIO is broken, don't do anything. */
void
init_sigio (int fd)
{
}

635
static void
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
reset_sigio (int fd)
{
}

void
request_sigio (void)
{
}

void
unrequest_sigio (void)
{
}

#else
Jim Blandy's avatar
Jim Blandy committed
651 652
#ifdef F_SETFL

653
int old_fcntl_flags[MAXDESC];
Jim Blandy's avatar
Jim Blandy committed
654

655
void
656
init_sigio (int fd)
Jim Blandy's avatar
Jim Blandy committed
657 658
{
#ifdef FASYNC
659 660
  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
661
#endif
662
  interrupts_deferred = 0;
Jim Blandy's avatar
Jim Blandy committed
663 664
}

665
static void
666
reset_sigio (int fd)
Jim Blandy's avatar
Jim Blandy committed
667
{
668
#ifdef FASYNC
669
  fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
670
#endif
Jim Blandy's avatar
Jim Blandy committed
671 672
}

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

677
void
678
request_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
679
{
680
  if (noninteractive)
681 682
    return;

Jim Blandy's avatar
Jim Blandy committed
683
#ifdef SIGWINCH
Jim Blandy's avatar
Jim Blandy committed
684
  sigunblock (sigmask (SIGWINCH));
Jim Blandy's avatar
Jim Blandy committed
685
#endif
Karoly Lorentey's avatar
Karoly Lorentey committed
686
  sigunblock (sigmask (SIGIO));
Jim Blandy's avatar
Jim Blandy committed
687 688 689 690

  interrupts_deferred = 0;
}

691
void
Karoly Lorentey's avatar
Karoly Lorentey committed
692
unrequest_sigio (void)
693
{
694 695 696 697 698
  if (noninteractive)
    return;

#if 0 /* XXX What's wrong with blocking SIGIO under X?  */
  if (x_display_list)
699
    return;
700
#endif
701

Jim Blandy's avatar
Jim Blandy committed
702
#ifdef SIGWINCH
Jim Blandy's avatar
Jim Blandy committed
703
  sigblock (sigmask (SIGWINCH));
Jim Blandy's avatar
Jim Blandy committed
704
#endif
Karoly Lorentey's avatar
Karoly Lorentey committed
705
  sigblock (sigmask (SIGIO));
Jim Blandy's avatar
Jim Blandy committed
706 707 708 709
  interrupts_deferred = 1;
}

#else /* no FASYNC */
710
#ifndef MSDOS
711

712
void
713
request_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
714
{
715
  if (noninteractive || read_socket_hook)
716 717
    return;

Jim Blandy's avatar
Jim Blandy committed
718 719
  croak ("request_sigio");
}
720

721
void
722
unrequest_sigio (void)
Jim Blandy's avatar
Jim Blandy committed
723
{
724
  if (noninteractive || read_socket_hook)
725 726
    return;

Jim Blandy's avatar
Jim Blandy committed
727 728
  croak ("unrequest_sigio");
}
729 730

#endif /* MSDOS */
Jim Blandy's avatar
Jim Blandy committed
731 732
#endif /* FASYNC */
#endif /* F_SETFL */
733
#endif /* SIGIO */
734 735


736 737 738 739 740 741
/* 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
742
emacs_get_tty (int fd, struct emacs_tty *settings)
743 744
{
  /* Retrieve the primary parameters - baud rate, character size, etcetera.  */
Dan Nicolaescu's avatar
Dan Nicolaescu committed
745
#ifndef DOS_NT
746
  /* We have those nifty POSIX tcmumbleattr functions.  */
747
  memset (&settings->main, 0, sizeof (settings->main));
748 749 750 751 752 753 754 755 756 757
  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
758
   *SETTINGS.  If FLUSHP is non-zero, we discard input.
759
   Return 0 if all went well, and -1 if anything failed.  */
760

761
int
762
emacs_set_tty (int fd, struct emacs_tty *settings, int flushp)
763 764
{
  /* Set the primary parameters - baud rate, character size, etcetera.  */
Dan Nicolaescu's avatar
Dan Nicolaescu committed
765
#ifndef DOS_NT
766
  int i;
767 768
  /* We have those nifty POSIX tcmumbleattr functions.
     William J. Smith <wjs@wiis.wang.com> writes:
769
     "POSIX 1003.1 defines tcsetattr to return success if it was
770 771 772 773
     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."  */
774
  /* This make sure that we don't loop indefinitely in here.  */
775
  for (i = 0 ; i < 10 ; i++)
776
    if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
777 778 779 780 781 782 783 784 785 786
      {
	if (errno == EINTR)
	  continue;
	else
	  return -1;
      }
    else
      {
	struct termios new;

787
	memset (&new, 0, sizeof (new));
788 789
	/* Get the current settings, and see if they're what we asked for.  */
	tcgetattr (fd, &new);
790 791 792 793 794 795 796 797
	/* 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
798
	    && memcmp (new.c_cc, settings->main.c_cc, NCCS) == 0)
799
	  break;
800 801
	else
	  continue;
802 803
      }
#endif
804

805 806 807 808
  /* We have survived the tempest.  */
  return 0;
}

Jim Blandy's avatar
Jim Blandy committed
809 810 811


#ifdef F_SETOWN
812
int old_fcntl_owner[MAXDESC];
Jim Blandy's avatar
Jim Blandy committed
813 814 815 816 817 818
#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.  */

819
#if defined (USG)
Jim Blandy's avatar
Jim Blandy committed
820 821 822 823
unsigned char _sobuf[BUFSIZ+8];
#else
char _sobuf[BUFSIZ];
#endif
824

825 826 827
/* Initialize the terminal mode on all tty devices that are currently
   open. */

828
void
829 830
init_all_sys_modes (void)
{
831
  struct tty_display_info *tty;
832
  for (tty = tty_list; tty; tty = tty->next)
833 834 835
    init_sys_modes (tty);
}

836 837
/* Initialize the terminal mode on the given tty device. */

838
void
839
init_sys_modes (struct tty_display_info *tty_out)
Jim Blandy's avatar
Jim Blandy committed
840
{
Jim Blandy's avatar
Jim Blandy committed
841 842
  struct emacs_tty tty;

843 844
  Vtty_erase_char = Qnil;