diff options
| author | Nick Roberts | 2009-08-13 13:22:55 +0000 |
|---|---|---|
| committer | Nick Roberts | 2009-08-13 13:22:55 +0000 |
| commit | 850d0752fb8ab02e3ffc80567578f9e9a4cb77f9 (patch) | |
| tree | abdfaa4a174ad4122539bcdd91de04ef20984c26 /src/process.c | |
| parent | 79a1c8a97058e8542a2fdbe3aabc4c513b79e46f (diff) | |
| download | emacs-850d0752fb8ab02e3ffc80567578f9e9a4cb77f9.tar.gz emacs-850d0752fb8ab02e3ffc80567578f9e9a4cb77f9.zip | |
(create_pty): New function.
(Fstart_process): Use it to allow Emacs to just associate a pty
with the buffer. See associated change in gdb-mi.el.
(list_processes_1): Deal with no program name.
(start_process_unwind): Use pid == -2 to mean no process.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 226 |
1 files changed, 158 insertions, 68 deletions
diff --git a/src/process.c b/src/process.c index 5b8a940b183..15ed971b3e2 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -284,6 +284,7 @@ static int keyboard_bit_set P_ ((SELECT_TYPE *)); | |||
| 284 | static void deactivate_process P_ ((Lisp_Object)); | 284 | static void deactivate_process P_ ((Lisp_Object)); |
| 285 | static void status_notify P_ ((struct Lisp_Process *)); | 285 | static void status_notify P_ ((struct Lisp_Process *)); |
| 286 | static int read_process_output P_ ((Lisp_Object, int)); | 286 | static int read_process_output P_ ((Lisp_Object, int)); |
| 287 | static void create_pty P_ ((Lisp_Object)); | ||
| 287 | 288 | ||
| 288 | /* If we support a window system, turn on the code to poll periodically | 289 | /* If we support a window system, turn on the code to poll periodically |
| 289 | to detect C-g. It isn't actually used when doing interrupt input. */ | 290 | to detect C-g. It isn't actually used when doing interrupt input. */ |
| @@ -1530,6 +1531,8 @@ list_processes_1 (query_only) | |||
| 1530 | while (1) | 1531 | while (1) |
| 1531 | { | 1532 | { |
| 1532 | tem1 = Fcar (tem); | 1533 | tem1 = Fcar (tem); |
| 1534 | if (NILP (tem1)) | ||
| 1535 | break; | ||
| 1533 | Finsert (1, &tem1); | 1536 | Finsert (1, &tem1); |
| 1534 | tem = Fcdr (tem); | 1537 | tem = Fcdr (tem); |
| 1535 | if (NILP (tem)) | 1538 | if (NILP (tem)) |
| @@ -1579,8 +1582,9 @@ at end of BUFFER, unless you specify an output stream or filter | |||
| 1579 | function to handle the output. BUFFER may also be nil, meaning that | 1582 | function to handle the output. BUFFER may also be nil, meaning that |
| 1580 | this process is not associated with any buffer. | 1583 | this process is not associated with any buffer. |
| 1581 | 1584 | ||
| 1582 | PROGRAM is the program file name. It is searched for in PATH. | 1585 | PROGRAM is the program file name. It is searched for in PATH. If |
| 1583 | Remaining arguments are strings to give program as arguments. | 1586 | nil, just associate a pty with the buffer. Remaining arguments are |
| 1587 | strings to give program as arguments. | ||
| 1584 | 1588 | ||
| 1585 | If you want to separate standard output from standard error, invoke | 1589 | If you want to separate standard output from standard error, invoke |
| 1586 | the command through a shell and redirect one of them using the shell | 1590 | the command through a shell and redirect one of them using the shell |
| @@ -1634,7 +1638,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1634 | 1638 | ||
| 1635 | program = args[2]; | 1639 | program = args[2]; |
| 1636 | 1640 | ||
| 1637 | CHECK_STRING (program); | 1641 | if (!NILP (program)) |
| 1642 | CHECK_STRING (program); | ||
| 1638 | 1643 | ||
| 1639 | proc = make_process (name); | 1644 | proc = make_process (name); |
| 1640 | /* If an error occurs and we can't start the process, we want to | 1645 | /* If an error occurs and we can't start the process, we want to |
| @@ -1680,7 +1685,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1680 | args2[0] = Qstart_process; | 1685 | args2[0] = Qstart_process; |
| 1681 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; | 1686 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; |
| 1682 | GCPRO2 (proc, current_dir); | 1687 | GCPRO2 (proc, current_dir); |
| 1683 | coding_systems = Ffind_operation_coding_system (nargs + 1, args2); | 1688 | if (!NILP (program)) |
| 1689 | coding_systems = Ffind_operation_coding_system (nargs + 1, args2); | ||
| 1684 | UNGCPRO; | 1690 | UNGCPRO; |
| 1685 | if (CONSP (coding_systems)) | 1691 | if (CONSP (coding_systems)) |
| 1686 | val = XCAR (coding_systems); | 1692 | val = XCAR (coding_systems); |
| @@ -1698,7 +1704,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1698 | args2[0] = Qstart_process; | 1704 | args2[0] = Qstart_process; |
| 1699 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; | 1705 | for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; |
| 1700 | GCPRO2 (proc, current_dir); | 1706 | GCPRO2 (proc, current_dir); |
| 1701 | coding_systems = Ffind_operation_coding_system (nargs + 1, args2); | 1707 | if (!NILP (program)) |
| 1708 | coding_systems = Ffind_operation_coding_system (nargs + 1, args2); | ||
| 1702 | UNGCPRO; | 1709 | UNGCPRO; |
| 1703 | } | 1710 | } |
| 1704 | if (CONSP (coding_systems)) | 1711 | if (CONSP (coding_systems)) |
| @@ -1709,80 +1716,86 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1709 | XPROCESS (proc)->encode_coding_system = val; | 1716 | XPROCESS (proc)->encode_coding_system = val; |
| 1710 | } | 1717 | } |
| 1711 | 1718 | ||
| 1712 | /* If program file name is not absolute, search our path for it. | ||
| 1713 | Put the name we will really use in TEM. */ | ||
| 1714 | if (!IS_DIRECTORY_SEP (SREF (program, 0)) | ||
| 1715 | && !(SCHARS (program) > 1 | ||
| 1716 | && IS_DEVICE_SEP (SREF (program, 1)))) | ||
| 1717 | { | ||
| 1718 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | ||
| 1719 | |||
| 1720 | tem = Qnil; | ||
| 1721 | GCPRO4 (name, program, buffer, current_dir); | ||
| 1722 | openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK)); | ||
| 1723 | UNGCPRO; | ||
| 1724 | if (NILP (tem)) | ||
| 1725 | report_file_error ("Searching for program", Fcons (program, Qnil)); | ||
| 1726 | tem = Fexpand_file_name (tem, Qnil); | ||
| 1727 | } | ||
| 1728 | else | ||
| 1729 | { | ||
| 1730 | if (!NILP (Ffile_directory_p (program))) | ||
| 1731 | error ("Specified program for new process is a directory"); | ||
| 1732 | tem = program; | ||
| 1733 | } | ||
| 1734 | 1719 | ||
| 1735 | /* If program file name starts with /: for quoting a magic name, | 1720 | XPROCESS (proc)->decoding_buf = make_uninit_string (0); |
| 1736 | discard that. */ | 1721 | XPROCESS (proc)->decoding_carryover = 0; |
| 1737 | if (SBYTES (tem) > 2 && SREF (tem, 0) == '/' | 1722 | XPROCESS (proc)->encoding_buf = make_uninit_string (0); |
| 1738 | && SREF (tem, 1) == ':') | ||
| 1739 | tem = Fsubstring (tem, make_number (2), Qnil); | ||
| 1740 | 1723 | ||
| 1741 | { | 1724 | XPROCESS (proc)->inherit_coding_system_flag |
| 1742 | struct gcpro gcpro1; | 1725 | = !(NILP (buffer) || !inherit_process_coding_system); |
| 1743 | GCPRO1 (tem); | ||
| 1744 | 1726 | ||
| 1745 | /* Encode the file name and put it in NEW_ARGV. | 1727 | if (!NILP (program)) |
| 1746 | That's where the child will use it to execute the program. */ | 1728 | { |
| 1747 | tem = Fcons (ENCODE_FILE (tem), Qnil); | 1729 | /* If program file name is not absolute, search our path for it. |
| 1730 | Put the name we will really use in TEM. */ | ||
| 1731 | if (!IS_DIRECTORY_SEP (SREF (program, 0)) | ||
| 1732 | && !(SCHARS (program) > 1 | ||
| 1733 | && IS_DEVICE_SEP (SREF (program, 1)))) | ||
| 1734 | { | ||
| 1735 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | ||
| 1736 | |||
| 1737 | tem = Qnil; | ||
| 1738 | GCPRO4 (name, program, buffer, current_dir); | ||
| 1739 | openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK)); | ||
| 1740 | UNGCPRO; | ||
| 1741 | if (NILP (tem)) | ||
| 1742 | report_file_error ("Searching for program", Fcons (program, Qnil)); | ||
| 1743 | tem = Fexpand_file_name (tem, Qnil); | ||
| 1744 | } | ||
| 1745 | else | ||
| 1746 | { | ||
| 1747 | if (!NILP (Ffile_directory_p (program))) | ||
| 1748 | error ("Specified program for new process is a directory"); | ||
| 1749 | tem = program; | ||
| 1750 | } | ||
| 1748 | 1751 | ||
| 1749 | /* Here we encode arguments by the coding system used for sending | 1752 | /* If program file name starts with /: for quoting a magic name, |
| 1750 | data to the process. We don't support using different coding | 1753 | discard that. */ |
| 1751 | systems for encoding arguments and for encoding data sent to the | 1754 | if (SBYTES (tem) > 2 && SREF (tem, 0) == '/' |
| 1752 | process. */ | 1755 | && SREF (tem, 1) == ':') |
| 1756 | tem = Fsubstring (tem, make_number (2), Qnil); | ||
| 1753 | 1757 | ||
| 1754 | for (i = 3; i < nargs; i++) | ||
| 1755 | { | 1758 | { |
| 1756 | tem = Fcons (args[i], tem); | 1759 | struct gcpro gcpro1; |
| 1757 | CHECK_STRING (XCAR (tem)); | 1760 | GCPRO1 (tem); |
| 1758 | if (STRING_MULTIBYTE (XCAR (tem))) | ||
| 1759 | XSETCAR (tem, | ||
| 1760 | code_convert_string_norecord | ||
| 1761 | (XCAR (tem), XPROCESS (proc)->encode_coding_system, 1)); | ||
| 1762 | } | ||
| 1763 | 1761 | ||
| 1764 | UNGCPRO; | 1762 | /* Encode the file name and put it in NEW_ARGV. |
| 1765 | } | 1763 | That's where the child will use it to execute the program. */ |
| 1764 | tem = Fcons (ENCODE_FILE (tem), Qnil); | ||
| 1766 | 1765 | ||
| 1767 | /* Now that everything is encoded we can collect the strings into | 1766 | /* Here we encode arguments by the coding system used for sending |
| 1768 | NEW_ARGV. */ | 1767 | data to the process. We don't support using different coding |
| 1769 | new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *)); | 1768 | systems for encoding arguments and for encoding data sent to the |
| 1770 | new_argv[nargs - 2] = 0; | 1769 | process. */ |
| 1771 | 1770 | ||
| 1772 | for (i = nargs - 3; i >= 0; i--) | 1771 | for (i = 3; i < nargs; i++) |
| 1773 | { | 1772 | { |
| 1774 | new_argv[i] = SDATA (XCAR (tem)); | 1773 | tem = Fcons (args[i], tem); |
| 1775 | tem = XCDR (tem); | 1774 | CHECK_STRING (XCAR (tem)); |
| 1776 | } | 1775 | if (STRING_MULTIBYTE (XCAR (tem))) |
| 1776 | XSETCAR (tem, | ||
| 1777 | code_convert_string_norecord | ||
| 1778 | (XCAR (tem), XPROCESS (proc)->encode_coding_system, 1)); | ||
| 1779 | } | ||
| 1777 | 1780 | ||
| 1778 | XPROCESS (proc)->decoding_buf = make_uninit_string (0); | 1781 | UNGCPRO; |
| 1779 | XPROCESS (proc)->decoding_carryover = 0; | 1782 | } |
| 1780 | XPROCESS (proc)->encoding_buf = make_uninit_string (0); | ||
| 1781 | 1783 | ||
| 1782 | XPROCESS (proc)->inherit_coding_system_flag | 1784 | /* Now that everything is encoded we can collect the strings into |
| 1783 | = !(NILP (buffer) || !inherit_process_coding_system); | 1785 | NEW_ARGV. */ |
| 1786 | new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *)); | ||
| 1787 | new_argv[nargs - 2] = 0; | ||
| 1784 | 1788 | ||
| 1785 | create_process (proc, (char **) new_argv, current_dir); | 1789 | for (i = nargs - 3; i >= 0; i--) |
| 1790 | { | ||
| 1791 | new_argv[i] = SDATA (XCAR (tem)); | ||
| 1792 | tem = XCDR (tem); | ||
| 1793 | } | ||
| 1794 | |||
| 1795 | create_process (proc, (char **) new_argv, current_dir); | ||
| 1796 | } | ||
| 1797 | else | ||
| 1798 | create_pty (proc); | ||
| 1786 | 1799 | ||
| 1787 | return unbind_to (count, proc); | 1800 | return unbind_to (count, proc); |
| 1788 | } | 1801 | } |
| @@ -1799,7 +1812,7 @@ start_process_unwind (proc) | |||
| 1799 | abort (); | 1812 | abort (); |
| 1800 | 1813 | ||
| 1801 | /* Was PROC started successfully? */ | 1814 | /* Was PROC started successfully? */ |
| 1802 | if (XPROCESS (proc)->pid <= 0) | 1815 | if (XPROCESS (proc)->pid == -1) |
| 1803 | remove_process (proc); | 1816 | remove_process (proc); |
| 1804 | 1817 | ||
| 1805 | return Qnil; | 1818 | return Qnil; |
| @@ -2268,6 +2281,83 @@ create_process (process, new_argv, current_dir) | |||
| 2268 | report_file_error ("Doing vfork", Qnil); | 2281 | report_file_error ("Doing vfork", Qnil); |
| 2269 | } | 2282 | } |
| 2270 | 2283 | ||
| 2284 | void | ||
| 2285 | create_pty (process) | ||
| 2286 | Lisp_Object process; | ||
| 2287 | { | ||
| 2288 | int inchannel, outchannel; | ||
| 2289 | |||
| 2290 | /* Use volatile to protect variables from being clobbered by longjmp. */ | ||
| 2291 | volatile int forkin, forkout; | ||
| 2292 | volatile int pty_flag = 0; | ||
| 2293 | |||
| 2294 | inchannel = outchannel = -1; | ||
| 2295 | |||
| 2296 | #ifdef HAVE_PTYS | ||
| 2297 | if (!NILP (Vprocess_connection_type)) | ||
| 2298 | outchannel = inchannel = allocate_pty (); | ||
| 2299 | |||
| 2300 | if (inchannel >= 0) | ||
| 2301 | { | ||
| 2302 | #if ! defined (USG) || defined (USG_SUBTTY_WORKS) | ||
| 2303 | /* On most USG systems it does not work to open the pty's tty here, | ||
| 2304 | then close it and reopen it in the child. */ | ||
| 2305 | #ifdef O_NOCTTY | ||
| 2306 | /* Don't let this terminal become our controlling terminal | ||
| 2307 | (in case we don't have one). */ | ||
| 2308 | forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); | ||
| 2309 | #else | ||
| 2310 | forkout = forkin = emacs_open (pty_name, O_RDWR, 0); | ||
| 2311 | #endif | ||
| 2312 | if (forkin < 0) | ||
| 2313 | report_file_error ("Opening pty", Qnil); | ||
| 2314 | #if defined (RTU) || defined (UNIPLUS) || defined (DONT_REOPEN_PTY) | ||
| 2315 | /* In the case that vfork is defined as fork, the parent process | ||
| 2316 | (Emacs) may send some data before the child process completes | ||
| 2317 | tty options setup. So we setup tty before forking. */ | ||
| 2318 | child_setup_tty (forkout); | ||
| 2319 | #endif /* RTU or UNIPLUS or DONT_REOPEN_PTY */ | ||
| 2320 | #else | ||
| 2321 | forkin = forkout = -1; | ||
| 2322 | #endif /* not USG, or USG_SUBTTY_WORKS */ | ||
| 2323 | pty_flag = 1; | ||
| 2324 | } | ||
| 2325 | #endif /* HAVE_PTYS */ | ||
| 2326 | |||
| 2327 | #ifdef O_NONBLOCK | ||
| 2328 | fcntl (inchannel, F_SETFL, O_NONBLOCK); | ||
| 2329 | fcntl (outchannel, F_SETFL, O_NONBLOCK); | ||
| 2330 | #else | ||
| 2331 | #ifdef O_NDELAY | ||
| 2332 | fcntl (inchannel, F_SETFL, O_NDELAY); | ||
| 2333 | fcntl (outchannel, F_SETFL, O_NDELAY); | ||
| 2334 | #endif | ||
| 2335 | #endif | ||
| 2336 | |||
| 2337 | /* Record this as an active process, with its channels. | ||
| 2338 | As a result, child_setup will close Emacs's side of the pipes. */ | ||
| 2339 | chan_process[inchannel] = process; | ||
| 2340 | XPROCESS (process)->infd = inchannel; | ||
| 2341 | XPROCESS (process)->outfd = outchannel; | ||
| 2342 | |||
| 2343 | /* Previously we recorded the tty descriptor used in the subprocess. | ||
| 2344 | It was only used for getting the foreground tty process, so now | ||
| 2345 | we just reopen the device (see emacs_get_tty_pgrp) as this is | ||
| 2346 | more portable (see USG_SUBTTY_WORKS above). */ | ||
| 2347 | |||
| 2348 | XPROCESS (process)->pty_flag = pty_flag; | ||
| 2349 | XPROCESS (process)->status = Qrun; | ||
| 2350 | setup_process_coding_systems (process); | ||
| 2351 | |||
| 2352 | FD_SET (inchannel, &input_wait_mask); | ||
| 2353 | FD_SET (inchannel, &non_keyboard_wait_mask); | ||
| 2354 | if (inchannel > max_process_desc) | ||
| 2355 | max_process_desc = inchannel; | ||
| 2356 | |||
| 2357 | XPROCESS (process)->pid = -2; | ||
| 2358 | XPROCESS (process)->tty_name = build_string (pty_name); | ||
| 2359 | } | ||
| 2360 | |||
| 2271 | 2361 | ||
| 2272 | #ifdef HAVE_SOCKETS | 2362 | #ifdef HAVE_SOCKETS |
| 2273 | 2363 | ||