diff options
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/emacsclient.c | 281 |
1 files changed, 196 insertions, 85 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 3c6215a0144..d544fa63356 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -41,6 +41,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 41 | char *w32_getenv (const char *); | 41 | char *w32_getenv (const char *); |
| 42 | # define egetenv(VAR) w32_getenv (VAR) | 42 | # define egetenv(VAR) w32_getenv (VAR) |
| 43 | 43 | ||
| 44 | # undef signal | ||
| 45 | |||
| 44 | #else /* !WINDOWSNT */ | 46 | #else /* !WINDOWSNT */ |
| 45 | 47 | ||
| 46 | # ifdef HAVE_NTGUI | 48 | # ifdef HAVE_NTGUI |
| @@ -68,8 +70,6 @@ char *w32_getenv (const char *); | |||
| 68 | 70 | ||
| 69 | #endif /* !WINDOWSNT */ | 71 | #endif /* !WINDOWSNT */ |
| 70 | 72 | ||
| 71 | #undef signal | ||
| 72 | |||
| 73 | #include <ctype.h> | 73 | #include <ctype.h> |
| 74 | #include <errno.h> | 74 | #include <errno.h> |
| 75 | #include <getopt.h> | 75 | #include <getopt.h> |
| @@ -144,7 +144,7 @@ static char const *server_file; | |||
| 144 | /* If non-NULL, the tramp prefix emacs must use to find the files. */ | 144 | /* If non-NULL, the tramp prefix emacs must use to find the files. */ |
| 145 | static char const *tramp_prefix; | 145 | static char const *tramp_prefix; |
| 146 | 146 | ||
| 147 | /* PID of the Emacs server process. */ | 147 | /* If nonzero, PID of the Emacs server process. */ |
| 148 | static pid_t emacs_pid; | 148 | static pid_t emacs_pid; |
| 149 | 149 | ||
| 150 | /* If non-NULL, a string that should form a frame parameter alist to | 150 | /* If non-NULL, a string that should form a frame parameter alist to |
| @@ -734,10 +734,13 @@ fail (void) | |||
| 734 | 734 | ||
| 735 | #if defined HAVE_SOCKETS && defined HAVE_INET_SOCKETS | 735 | #if defined HAVE_SOCKETS && defined HAVE_INET_SOCKETS |
| 736 | 736 | ||
| 737 | enum { AUTH_KEY_LENGTH = 64 }; | 737 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 738 | static void act_on_signals (HSOCKET); | ||
| 739 | # else | ||
| 740 | static void act_on_signals (HSOCKET s) {} | ||
| 741 | # endif | ||
| 738 | 742 | ||
| 739 | /* Socket used to communicate with the Emacs server process. */ | 743 | enum { AUTH_KEY_LENGTH = 64 }; |
| 740 | static HSOCKET emacs_socket = 0; | ||
| 741 | 744 | ||
| 742 | static void | 745 | static void |
| 743 | sock_err_message (const char *function_name) | 746 | sock_err_message (const char *function_name) |
| @@ -790,16 +793,22 @@ send_to_emacs (HSOCKET s, const char *data) | |||
| 790 | if (sblen == SEND_BUFFER_SIZE | 793 | if (sblen == SEND_BUFFER_SIZE |
| 791 | || (0 < sblen && send_buffer[sblen - 1] == '\n')) | 794 | || (0 < sblen && send_buffer[sblen - 1] == '\n')) |
| 792 | { | 795 | { |
| 793 | int sent = send (s, send_buffer, sblen, 0); | 796 | int sent; |
| 794 | if (sent < 0) | 797 | while ((sent = send (s, send_buffer, sblen, 0)) < 0) |
| 795 | { | 798 | { |
| 796 | message (true, "%s: failed to send %d bytes to socket: %s\n", | 799 | if (errno != EINTR) |
| 797 | progname, sblen, strerror (errno)); | 800 | { |
| 798 | fail (); | 801 | message (true, "%s: failed to send %d bytes to socket: %s\n", |
| 802 | progname, sblen, strerror (errno)); | ||
| 803 | fail (); | ||
| 804 | } | ||
| 805 | /* Act on signals not requiring communication to Emacs, | ||
| 806 | but defer action on the others to avoid confusing the | ||
| 807 | communication currently in progress. */ | ||
| 808 | act_on_signals (INVALID_SOCKET); | ||
| 799 | } | 809 | } |
| 800 | if (sent != sblen) | ||
| 801 | memmove (send_buffer, &send_buffer[sent], sblen - sent); | ||
| 802 | sblen -= sent; | 810 | sblen -= sent; |
| 811 | memmove (send_buffer, &send_buffer[sent], sblen); | ||
| 803 | } | 812 | } |
| 804 | 813 | ||
| 805 | dlen -= part; | 814 | dlen -= part; |
| @@ -1091,86 +1100,181 @@ socket_status (const char *name) | |||
| 1091 | } | 1100 | } |
| 1092 | 1101 | ||
| 1093 | 1102 | ||
| 1094 | /* A signal handler that passes the signal to the Emacs process. | 1103 | /* Signal handlers merely set a flag, to avoid race conditions on |
| 1095 | Useful for SIGWINCH. */ | 1104 | POSIXish systems. Non-POSIX platforms lacking sigaction make do |
| 1096 | 1105 | with traditional calls to 'signal'; races are rare so this usually | |
| 1106 | works. Although this approach may treat multiple deliveries of SIG | ||
| 1107 | as a single delivery and may act on signals in a different order | ||
| 1108 | than received, that is OK for emacsclient. Also, this approach may | ||
| 1109 | omit output if a printf call is interrupted by a signal, but printf | ||
| 1110 | output is not that important (emacsclient does not check for printf | ||
| 1111 | errors, after all) so this is also OK for emacsclient. */ | ||
| 1112 | |||
| 1113 | /* Reinstall for SIG the signal handler HANDLER if needed. It is | ||
| 1114 | needed on a non-POSIX or traditional platform where an interrupt | ||
| 1115 | resets the signal handler to SIG_DFL. */ | ||
| 1097 | static void | 1116 | static void |
| 1098 | pass_signal_to_emacs (int signalnum) | 1117 | reinstall_handler_if_needed (int sig, void (*handler) (int)) |
| 1099 | { | 1118 | { |
| 1100 | int old_errno = errno; | 1119 | # ifndef SA_RESETHAND |
| 1120 | /* This is a platform without POSIX's sigaction. */ | ||
| 1121 | signal (sig, handler); | ||
| 1122 | # endif | ||
| 1123 | } | ||
| 1101 | 1124 | ||
| 1102 | if (emacs_pid) | 1125 | /* Flags for each signal, and handlers that set the flags. */ |
| 1103 | kill (emacs_pid, signalnum); | ||
| 1104 | 1126 | ||
| 1105 | signal (signalnum, pass_signal_to_emacs); | 1127 | static sig_atomic_t volatile |
| 1106 | errno = old_errno; | 1128 | got_sigcont, got_sigtstp, got_sigttou, got_sigwinch; |
| 1129 | |||
| 1130 | static void | ||
| 1131 | handle_sigcont (int sig) | ||
| 1132 | { | ||
| 1133 | got_sigcont = 1; | ||
| 1134 | reinstall_handler_if_needed (sig, handle_sigcont); | ||
| 1135 | } | ||
| 1136 | static void | ||
| 1137 | handle_sigtstp (int sig) | ||
| 1138 | { | ||
| 1139 | got_sigtstp = 1; | ||
| 1140 | reinstall_handler_if_needed (sig, handle_sigtstp); | ||
| 1141 | } | ||
| 1142 | static void | ||
| 1143 | handle_sigttou (int sig) | ||
| 1144 | { | ||
| 1145 | got_sigttou = 1; | ||
| 1146 | reinstall_handler_if_needed (sig, handle_sigttou); | ||
| 1147 | } | ||
| 1148 | static void | ||
| 1149 | handle_sigwinch (int sig) | ||
| 1150 | { | ||
| 1151 | got_sigwinch = 1; | ||
| 1152 | reinstall_handler_if_needed (sig, handle_sigwinch); | ||
| 1107 | } | 1153 | } |
| 1108 | 1154 | ||
| 1109 | /* Signal handler for SIGCONT; notify the Emacs process that it can | 1155 | /* Install for signal SIG the handler HANDLER. However, if FLAG is |
| 1110 | now resume our tty frame. */ | 1156 | non-null and if the signal is currently being ignored, do not |
| 1157 | install the handler and keep *FLAG zero. */ | ||
| 1111 | 1158 | ||
| 1112 | static void | 1159 | static void |
| 1113 | handle_sigcont (int signalnum) | 1160 | install_handler (int sig, void (*handler) (int), sig_atomic_t volatile *flag) |
| 1114 | { | 1161 | { |
| 1115 | int old_errno = errno; | 1162 | # ifdef SA_RESETHAND |
| 1116 | pid_t pgrp = getpgrp (); | 1163 | if (flag) |
| 1117 | pid_t tcpgrp = tcgetpgrp (STDOUT_FILENO); | ||
| 1118 | |||
| 1119 | if (tcpgrp == pgrp) | ||
| 1120 | { | 1164 | { |
| 1121 | /* We are in the foreground. */ | 1165 | struct sigaction oact; |
| 1122 | send_to_emacs (emacs_socket, "-resume \n"); | 1166 | if (sigaction (sig, NULL, &oact) == 0 && oact.sa_handler == SIG_IGN) |
| 1167 | return; | ||
| 1123 | } | 1168 | } |
| 1124 | else if (0 <= tcpgrp && tty) | 1169 | struct sigaction act = { .sa_handler = handler }; |
| 1170 | sigemptyset (&act.sa_mask); | ||
| 1171 | sigaction (sig, &act, NULL); | ||
| 1172 | # else | ||
| 1173 | void (*ohandler) (int) = signal (sig, handler); | ||
| 1174 | if (flag) | ||
| 1125 | { | 1175 | { |
| 1126 | /* We are in the background; cancel the continue. */ | 1176 | if (ohandler == SIG_IGN) |
| 1127 | kill (-pgrp, SIGTTIN); | 1177 | { |
| 1178 | signal (sig, SIG_IGN); | ||
| 1179 | /* While HANDLER was mistakenly installed a signal may have | ||
| 1180 | arrived and set *FLAG, so clear *FLAG now. */ | ||
| 1181 | *flag = 0; | ||
| 1182 | } | ||
| 1128 | } | 1183 | } |
| 1129 | 1184 | # endif | |
| 1130 | signal (signalnum, handle_sigcont); | ||
| 1131 | errno = old_errno; | ||
| 1132 | } | 1185 | } |
| 1133 | 1186 | ||
| 1134 | /* Signal handler for SIGTSTP; notify the Emacs process that we are | 1187 | /* Initial installation of signal handlers. */ |
| 1135 | going to sleep. Normally the suspend is initiated by Emacs via | ||
| 1136 | server-handle-suspend-tty, but if the server gets out of sync with | ||
| 1137 | reality, we may get a SIGTSTP on C-z. Handling this signal and | ||
| 1138 | notifying Emacs about it should get things under control again. */ | ||
| 1139 | 1188 | ||
| 1140 | static void | 1189 | static void |
| 1141 | handle_sigtstp (int signalnum) | 1190 | init_signals (void) |
| 1142 | { | 1191 | { |
| 1143 | int old_errno = errno; | 1192 | install_handler (SIGCONT, handle_sigcont, &got_sigcont); |
| 1144 | sigset_t set; | 1193 | install_handler (SIGTSTP, handle_sigtstp, &got_sigtstp); |
| 1145 | 1194 | install_handler (SIGTTOU, handle_sigttou, &got_sigttou); | |
| 1146 | if (emacs_socket) | 1195 | install_handler (SIGWINCH, handle_sigwinch, &got_sigwinch); |
| 1147 | send_to_emacs (emacs_socket, "-suspend \n"); | 1196 | /* Don't mess with SIGINT and SIGQUIT, as Emacs has no way to |
| 1148 | 1197 | determine which terminal the signal came from. C-g is a normal | |
| 1149 | /* Unblock this signal and call the default handler by temporarily | 1198 | input event on secondary terminals. */ |
| 1150 | changing the handler and resignaling. */ | ||
| 1151 | sigprocmask (SIG_BLOCK, NULL, &set); | ||
| 1152 | sigdelset (&set, signalnum); | ||
| 1153 | signal (signalnum, SIG_DFL); | ||
| 1154 | raise (signalnum); | ||
| 1155 | sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */ | ||
| 1156 | signal (signalnum, handle_sigtstp); | ||
| 1157 | |||
| 1158 | errno = old_errno; | ||
| 1159 | } | 1199 | } |
| 1160 | 1200 | ||
| 1201 | /* Act on delivered tty-related signal SIG that normally has handler | ||
| 1202 | HANDLER. EMACS_SOCKET connects to Emacs. */ | ||
| 1161 | 1203 | ||
| 1162 | /* Set up signal handlers before opening a frame on the current tty. */ | 1204 | static void |
| 1205 | act_on_tty_signal (int sig, void (*handler) (int), HSOCKET emacs_socket) | ||
| 1206 | { | ||
| 1207 | /* Notify Emacs that we are going to sleep. Normally the suspend is | ||
| 1208 | initiated by Emacs via server-handle-suspend-tty, but if the | ||
| 1209 | server gets out of sync with reality, we may get a SIGTSTP on | ||
| 1210 | C-z. Handling this signal and notifying Emacs about it should | ||
| 1211 | get things under control again. */ | ||
| 1212 | send_to_emacs (emacs_socket, "-suspend \n"); | ||
| 1213 | |||
| 1214 | /* Execute the default action by temporarily changing handling to | ||
| 1215 | the default and resignaling. */ | ||
| 1216 | install_handler (sig, SIG_DFL, NULL); | ||
| 1217 | raise (sig); | ||
| 1218 | install_handler (sig, handler, NULL); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | /* Act on delivered signals if possible. If EMACS_SOCKET is valid, | ||
| 1222 | use it to communicate to Emacs. */ | ||
| 1163 | 1223 | ||
| 1164 | static void | 1224 | static void |
| 1165 | init_signals (void) | 1225 | act_on_signals (HSOCKET emacs_socket) |
| 1166 | { | 1226 | { |
| 1167 | /* Don't pass SIGINT and SIGQUIT to Emacs, because it has no way of | 1227 | while (true) |
| 1168 | deciding which terminal the signal came from. C-g is now a | 1228 | { |
| 1169 | normal input event on secondary terminals. */ | 1229 | bool took_action = false; |
| 1170 | signal (SIGWINCH, pass_signal_to_emacs); | 1230 | |
| 1171 | signal (SIGCONT, handle_sigcont); | 1231 | if (emacs_socket != INVALID_SOCKET) |
| 1172 | signal (SIGTSTP, handle_sigtstp); | 1232 | { |
| 1173 | signal (SIGTTOU, handle_sigtstp); | 1233 | if (got_sigcont) |
| 1234 | { | ||
| 1235 | got_sigcont = 0; | ||
| 1236 | took_action = true; | ||
| 1237 | pid_t tcpgrp = tcgetpgrp (STDOUT_FILENO); | ||
| 1238 | if (0 <= tcpgrp) | ||
| 1239 | { | ||
| 1240 | pid_t pgrp = getpgrp (); | ||
| 1241 | if (tcpgrp == pgrp) | ||
| 1242 | { | ||
| 1243 | /* We are in the foreground. */ | ||
| 1244 | send_to_emacs (emacs_socket, "-resume \n"); | ||
| 1245 | } | ||
| 1246 | else if (tty) | ||
| 1247 | { | ||
| 1248 | /* We are in the background; cancel the continue. */ | ||
| 1249 | kill (-pgrp, SIGTTIN); | ||
| 1250 | } | ||
| 1251 | } | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | if (got_sigtstp) | ||
| 1255 | { | ||
| 1256 | got_sigtstp = 0; | ||
| 1257 | took_action = true; | ||
| 1258 | act_on_tty_signal (SIGTSTP, handle_sigtstp, emacs_socket); | ||
| 1259 | } | ||
| 1260 | if (got_sigttou) | ||
| 1261 | { | ||
| 1262 | got_sigttou = 0; | ||
| 1263 | took_action = true; | ||
| 1264 | act_on_tty_signal (SIGTTOU, handle_sigttou, emacs_socket); | ||
| 1265 | } | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | if (emacs_pid && got_sigwinch) | ||
| 1269 | { | ||
| 1270 | got_sigwinch = 0; | ||
| 1271 | took_action = true; | ||
| 1272 | kill (emacs_pid, SIGWINCH); | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | if (!took_action) | ||
| 1276 | break; | ||
| 1277 | } | ||
| 1174 | } | 1278 | } |
| 1175 | 1279 | ||
| 1176 | /* Create a local socket and connect it to Emacs. */ | 1280 | /* Create a local socket and connect it to Emacs. */ |
| @@ -1464,7 +1568,7 @@ w32_give_focus (void) | |||
| 1464 | 1568 | ||
| 1465 | /* Start the emacs daemon and try to connect to it. */ | 1569 | /* Start the emacs daemon and try to connect to it. */ |
| 1466 | 1570 | ||
| 1467 | static void | 1571 | static HSOCKET |
| 1468 | start_daemon_and_retry_set_socket (void) | 1572 | start_daemon_and_retry_set_socket (void) |
| 1469 | { | 1573 | { |
| 1470 | # ifndef WINDOWSNT | 1574 | # ifndef WINDOWSNT |
| @@ -1581,13 +1685,23 @@ start_daemon_and_retry_set_socket (void) | |||
| 1581 | "Emacs daemon should have started, trying to connect again\n"); | 1685 | "Emacs daemon should have started, trying to connect again\n"); |
| 1582 | # endif /* WINDOWSNT */ | 1686 | # endif /* WINDOWSNT */ |
| 1583 | 1687 | ||
| 1584 | emacs_socket = set_socket (true); | 1688 | HSOCKET emacs_socket = set_socket (true); |
| 1585 | if (emacs_socket == INVALID_SOCKET) | 1689 | if (emacs_socket == INVALID_SOCKET) |
| 1586 | { | 1690 | { |
| 1587 | message (true, | 1691 | message (true, |
| 1588 | "Error: Cannot connect even after starting the Emacs daemon\n"); | 1692 | "Error: Cannot connect even after starting the Emacs daemon\n"); |
| 1589 | exit (EXIT_FAILURE); | 1693 | exit (EXIT_FAILURE); |
| 1590 | } | 1694 | } |
| 1695 | return emacs_socket; | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | /* Flush standard output and its underlying file descriptor. */ | ||
| 1699 | static void | ||
| 1700 | flush_stdout (HSOCKET emacs_socket) | ||
| 1701 | { | ||
| 1702 | fflush (stdout); | ||
| 1703 | while (fdatasync (STDOUT_FILENO) != 0 && errno == EINTR) | ||
| 1704 | act_on_signals (emacs_socket); | ||
| 1591 | } | 1705 | } |
| 1592 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ | 1706 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ |
| 1593 | 1707 | ||
| @@ -1641,13 +1755,14 @@ main (int argc, char **argv) | |||
| 1641 | in case of failure to connect. */ | 1755 | in case of failure to connect. */ |
| 1642 | bool start_daemon_if_needed = alternate_editor && !alternate_editor[0]; | 1756 | bool start_daemon_if_needed = alternate_editor && !alternate_editor[0]; |
| 1643 | 1757 | ||
| 1644 | emacs_socket = set_socket (alternate_editor || start_daemon_if_needed); | 1758 | HSOCKET emacs_socket = set_socket (alternate_editor |
| 1759 | || start_daemon_if_needed); | ||
| 1645 | if (emacs_socket == INVALID_SOCKET) | 1760 | if (emacs_socket == INVALID_SOCKET) |
| 1646 | { | 1761 | { |
| 1647 | if (! start_daemon_if_needed) | 1762 | if (! start_daemon_if_needed) |
| 1648 | fail (); | 1763 | fail (); |
| 1649 | 1764 | ||
| 1650 | start_daemon_and_retry_set_socket (); | 1765 | emacs_socket = start_daemon_and_retry_set_socket (); |
| 1651 | } | 1766 | } |
| 1652 | 1767 | ||
| 1653 | char *cwd = get_current_dir_name (); | 1768 | char *cwd = get_current_dir_name (); |
| @@ -1719,6 +1834,8 @@ main (int argc, char **argv) | |||
| 1719 | if (find_tty (&tty_type, &tty_name, !tty)) | 1834 | if (find_tty (&tty_type, &tty_name, !tty)) |
| 1720 | { | 1835 | { |
| 1721 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM | 1836 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 1837 | /* Install signal handlers before opening a frame on the | ||
| 1838 | current tty. */ | ||
| 1722 | init_signals (); | 1839 | init_signals (); |
| 1723 | # endif | 1840 | # endif |
| 1724 | send_to_emacs (emacs_socket, "-tty "); | 1841 | send_to_emacs (emacs_socket, "-tty "); |
| @@ -1809,20 +1926,16 @@ main (int argc, char **argv) | |||
| 1809 | printf ("Waiting for Emacs..."); | 1926 | printf ("Waiting for Emacs..."); |
| 1810 | skiplf = false; | 1927 | skiplf = false; |
| 1811 | } | 1928 | } |
| 1812 | fflush (stdout); | 1929 | flush_stdout (emacs_socket); |
| 1813 | while (fdatasync (STDOUT_FILENO) != 0 && errno == EINTR) | ||
| 1814 | continue; | ||
| 1815 | 1930 | ||
| 1816 | /* Now, wait for an answer and print any messages. */ | 1931 | /* Now, wait for an answer and print any messages. */ |
| 1817 | while (exit_status == EXIT_SUCCESS) | 1932 | while (exit_status == EXIT_SUCCESS) |
| 1818 | { | 1933 | { |
| 1819 | do | 1934 | do |
| 1820 | { | 1935 | { |
| 1821 | errno = 0; | 1936 | act_on_signals (emacs_socket); |
| 1822 | rl = recv (emacs_socket, string, BUFSIZ, 0); | 1937 | rl = recv (emacs_socket, string, BUFSIZ, 0); |
| 1823 | } | 1938 | } |
| 1824 | /* If we receive a signal (e.g. SIGWINCH, which we pass | ||
| 1825 | through to Emacs), on some OSes we get EINTR and must retry. */ | ||
| 1826 | while (rl < 0 && errno == EINTR); | 1939 | while (rl < 0 && errno == EINTR); |
| 1827 | 1940 | ||
| 1828 | if (rl <= 0) | 1941 | if (rl <= 0) |
| @@ -1916,9 +2029,7 @@ main (int argc, char **argv) | |||
| 1916 | 2029 | ||
| 1917 | if (!skiplf) | 2030 | if (!skiplf) |
| 1918 | printf ("\n"); | 2031 | printf ("\n"); |
| 1919 | fflush (stdout); | 2032 | flush_stdout (emacs_socket); |
| 1920 | while (fdatasync (STDOUT_FILENO) != 0 && errno == EINTR) | ||
| 1921 | continue; | ||
| 1922 | 2033 | ||
| 1923 | if (rl < 0) | 2034 | if (rl < 0) |
| 1924 | exit_status = EXIT_FAILURE; | 2035 | exit_status = EXIT_FAILURE; |