blob: 67be1d75ee1e16305952bd66d03d5d4b27bc2715 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaare0874f82016-01-24 20:36:41 +01002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 */
8
9/*
10 * Implements communication through a socket or any file handle.
11 */
12
13#include "vim.h"
14
Bram Moolenaar509ce2a2016-03-11 22:52:15 +010015#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +010016
Bram Moolenaard04a0202016-01-26 23:30:18 +010017/* TRUE when netbeans is running with a GUI. */
18#ifdef FEAT_GUI
19# define CH_HAS_GUI (gui.in_use || gui.starting)
20#endif
21
Bram Moolenaar3f7d0902016-11-12 21:13:42 +010022/* Note: when making changes here also adjust configure.ac. */
Bram Moolenaard04a0202016-01-26 23:30:18 +010023#ifdef WIN32
24/* WinSock API is separated from C API, thus we can't use read(), write(),
25 * errno... */
26# define SOCK_ERRNO errno = WSAGetLastError()
27# undef ECONNREFUSED
28# define ECONNREFUSED WSAECONNREFUSED
Bram Moolenaar4d919d72016-02-05 22:36:41 +010029# undef EWOULDBLOCK
30# define EWOULDBLOCK WSAEWOULDBLOCK
Bram Moolenaard42119f2016-02-28 20:51:49 +010031# undef EINPROGRESS
32# define EINPROGRESS WSAEINPROGRESS
Bram Moolenaard04a0202016-01-26 23:30:18 +010033# ifdef EINTR
34# undef EINTR
35# endif
36# define EINTR WSAEINTR
Bram Moolenaard8070362016-02-15 21:56:54 +010037# define sock_write(sd, buf, len) send((SOCKET)sd, buf, len, 0)
38# define sock_read(sd, buf, len) recv((SOCKET)sd, buf, len, 0)
39# define sock_close(sd) closesocket((SOCKET)sd)
Bram Moolenaard04a0202016-01-26 23:30:18 +010040#else
41# include <netdb.h>
42# include <netinet/in.h>
43
44# include <sys/socket.h>
45# ifdef HAVE_LIBGEN_H
46# include <libgen.h>
47# endif
48# define SOCK_ERRNO
49# define sock_write(sd, buf, len) write(sd, buf, len)
50# define sock_read(sd, buf, len) read(sd, buf, len)
51# define sock_close(sd) close(sd)
Bram Moolenaar0943a092016-02-16 13:11:17 +010052# define fd_read(fd, buf, len) read(fd, buf, len)
Bram Moolenaard8070362016-02-15 21:56:54 +010053# define fd_write(sd, buf, len) write(sd, buf, len)
54# define fd_close(sd) close(sd)
Bram Moolenaard04a0202016-01-26 23:30:18 +010055#endif
56
Bram Moolenaardc0ccae2016-10-09 17:28:01 +020057static void channel_read(channel_T *channel, ch_part_T part, char *func);
Bram Moolenaarb2658a12016-04-26 17:16:24 +020058
Bram Moolenaar187db502016-02-27 14:44:26 +010059/* Whether a redraw is needed for appending a line to a buffer. */
60static int channel_need_redraw = FALSE;
61
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +020062/* Whether we are inside channel_parse_messages() or another situation where it
63 * is safe to invoke callbacks. */
64static int safe_to_invoke_callback = 0;
Bram Moolenaar187db502016-02-27 14:44:26 +010065
Bram Moolenaarde7eb0a2016-05-09 20:54:33 +020066static char *part_names[] = {"sock", "out", "err", "in"};
67
Bram Moolenaard8070362016-02-15 21:56:54 +010068#ifdef WIN32
69 static int
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +010070fd_read(sock_T fd, char *buf, size_t len)
Bram Moolenaard8070362016-02-15 21:56:54 +010071{
72 HANDLE h = (HANDLE)fd;
73 DWORD nread;
74
75 if (!ReadFile(h, buf, (DWORD)len, &nread, NULL))
76 return -1;
77 return (int)nread;
78}
79
80 static int
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +010081fd_write(sock_T fd, char *buf, size_t len)
Bram Moolenaard8070362016-02-15 21:56:54 +010082{
83 HANDLE h = (HANDLE)fd;
84 DWORD nwrite;
85
86 if (!WriteFile(h, buf, (DWORD)len, &nwrite, NULL))
87 return -1;
88 return (int)nwrite;
89}
90
91 static void
92fd_close(sock_T fd)
93{
94 HANDLE h = (HANDLE)fd;
95
96 CloseHandle(h);
97}
98#endif
Bram Moolenaare0874f82016-01-24 20:36:41 +010099
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100100/* Log file opened with ch_logfile(). */
101static FILE *log_fd = NULL;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100102#ifdef FEAT_RELTIME
103static proftime_T log_start;
104#endif
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100105
106 void
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100107ch_logfile(char_u *fname, char_u *opt)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100108{
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100109 FILE *file = NULL;
110
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100111 if (log_fd != NULL)
112 fclose(log_fd);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100113
114 if (*fname != NUL)
115 {
116 file = fopen((char *)fname, *opt == 'w' ? "w" : "a");
117 if (file == NULL)
118 {
119 EMSG2(_(e_notopen), fname);
120 return;
121 }
122 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100123 log_fd = file;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100124
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100125 if (log_fd != NULL)
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100126 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100127 fprintf(log_fd, "==== start log session ====\n");
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100128#ifdef FEAT_RELTIME
129 profile_start(&log_start);
130#endif
131 }
132}
133
134 int
Bram Moolenaarcf089462016-06-12 21:18:43 +0200135ch_log_active(void)
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100136{
137 return log_fd != NULL;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100138}
139
140 static void
Bram Moolenaar71eeb742017-09-13 22:18:01 +0200141ch_log_lead(const char *what, channel_T *ch)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100142{
143 if (log_fd != NULL)
144 {
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100145#ifdef FEAT_RELTIME
146 proftime_T log_now;
147
148 profile_start(&log_now);
149 profile_sub(&log_now, &log_start);
150 fprintf(log_fd, "%s ", profile_msg(&log_now));
151#endif
Bram Moolenaar77073442016-02-13 23:23:53 +0100152 if (ch != NULL)
153 fprintf(log_fd, "%son %d: ", what, ch->ch_id);
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100154 else
155 fprintf(log_fd, "%s: ", what);
156 }
157}
158
Bram Moolenaard0b65022016-03-06 21:50:33 +0100159static int did_log_msg = TRUE;
160
Bram Moolenaar4ac2e8d2018-04-08 12:38:26 +0200161#ifndef PROTO /* prototype is in vim.h */
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100162 void
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200163ch_log(channel_T *ch, const char *fmt, ...)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100164{
165 if (log_fd != NULL)
166 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200167 va_list ap;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100168
Bram Moolenaar77073442016-02-13 23:23:53 +0100169 ch_log_lead("", ch);
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200170 va_start(ap, fmt);
171 vfprintf(log_fd, fmt, ap);
172 va_end(ap);
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100173 fputc('\n', log_fd);
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100174 fflush(log_fd);
Bram Moolenaard0b65022016-03-06 21:50:33 +0100175 did_log_msg = TRUE;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100176 }
177}
Bram Moolenaar4ac2e8d2018-04-08 12:38:26 +0200178#endif
179
180 static void
181ch_error(channel_T *ch, const char *fmt, ...)
Bram Moolenaare80757c2018-04-10 12:42:44 +0200182#ifdef USE_PRINTF_FORMAT_ATTRIBUTE
183 __attribute__((format(printf, 2, 3)))
Bram Moolenaar4ac2e8d2018-04-08 12:38:26 +0200184#endif
185 ;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100186
187 static void
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200188ch_error(channel_T *ch, const char *fmt, ...)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100189{
190 if (log_fd != NULL)
191 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200192 va_list ap;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100193
Bram Moolenaar77073442016-02-13 23:23:53 +0100194 ch_log_lead("ERR ", ch);
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200195 va_start(ap, fmt);
196 vfprintf(log_fd, fmt, ap);
197 va_end(ap);
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100198 fputc('\n', log_fd);
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100199 fflush(log_fd);
Bram Moolenaard0b65022016-03-06 21:50:33 +0100200 did_log_msg = TRUE;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100201 }
202}
Bram Moolenaard04a0202016-01-26 23:30:18 +0100203
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100204#ifdef _WIN32
205# undef PERROR
206# define PERROR(msg) (void)emsg3((char_u *)"%s: %s", \
207 (char_u *)msg, (char_u *)strerror_win32(errno))
208
209 static char *
210strerror_win32(int eno)
211{
212 static LPVOID msgbuf = NULL;
213 char_u *ptr;
214
215 if (msgbuf)
Bram Moolenaaraad30bb2016-06-26 17:31:03 +0200216 {
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100217 LocalFree(msgbuf);
Bram Moolenaaraad30bb2016-06-26 17:31:03 +0200218 msgbuf = NULL;
219 }
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100220 FormatMessage(
221 FORMAT_MESSAGE_ALLOCATE_BUFFER |
222 FORMAT_MESSAGE_FROM_SYSTEM |
223 FORMAT_MESSAGE_IGNORE_INSERTS,
224 NULL,
225 eno,
226 MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
227 (LPTSTR) &msgbuf,
228 0,
229 NULL);
Bram Moolenaaraad30bb2016-06-26 17:31:03 +0200230 if (msgbuf != NULL)
231 /* chomp \r or \n */
232 for (ptr = (char_u *)msgbuf; *ptr; ptr++)
233 switch (*ptr)
234 {
235 case '\r':
236 STRMOVE(ptr, ptr + 1);
237 ptr--;
238 break;
239 case '\n':
240 if (*(ptr + 1) == '\0')
241 *ptr = '\0';
242 else
243 *ptr = ' ';
244 break;
245 }
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100246 return msgbuf;
247}
248#endif
249
Bram Moolenaar77073442016-02-13 23:23:53 +0100250/*
251 * The list of all allocated channels.
252 */
253static channel_T *first_channel = NULL;
254static int next_ch_id = 0;
255
256/*
257 * Allocate a new channel. The refcount is set to 1.
258 * The channel isn't actually used until it is opened.
259 * Returns NULL if out of memory.
260 */
261 channel_T *
262add_channel(void)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100263{
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200264 ch_part_T part;
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100265 channel_T *channel = (channel_T *)alloc_clear((int)sizeof(channel_T));
Bram Moolenaare0874f82016-01-24 20:36:41 +0100266
Bram Moolenaar77073442016-02-13 23:23:53 +0100267 if (channel == NULL)
268 return NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100269
Bram Moolenaar77073442016-02-13 23:23:53 +0100270 channel->ch_id = next_ch_id++;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100271 ch_log(channel, "Created channel");
Bram Moolenaar77073442016-02-13 23:23:53 +0100272
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200273 for (part = PART_SOCK; part < PART_COUNT; ++part)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100274 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100275 channel->ch_part[part].ch_fd = INVALID_FD;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100276#ifdef FEAT_GUI_X11
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100277 channel->ch_part[part].ch_inputHandler = (XtInputId)NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100278#endif
279#ifdef FEAT_GUI_GTK
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100280 channel->ch_part[part].ch_inputHandler = 0;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100281#endif
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100282 channel->ch_part[part].ch_timeout = 2000;
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100283 }
Bram Moolenaare0874f82016-01-24 20:36:41 +0100284
Bram Moolenaar77073442016-02-13 23:23:53 +0100285 if (first_channel != NULL)
286 {
287 first_channel->ch_prev = channel;
288 channel->ch_next = first_channel;
289 }
290 first_channel = channel;
291
292 channel->ch_refcount = 1;
293 return channel;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100294}
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100295
Bram Moolenaarb9c31e72016-09-29 15:18:57 +0200296 int
297has_any_channel(void)
298{
299 return first_channel != NULL;
300}
301
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100302/*
Bram Moolenaard6051b52016-02-28 15:49:03 +0100303 * Called when the refcount of a channel is zero.
Bram Moolenaar46c85432016-02-26 11:17:46 +0100304 * Return TRUE if "channel" has a callback and the associated job wasn't
305 * killed.
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100306 */
307 static int
Bram Moolenaar46c85432016-02-26 11:17:46 +0100308channel_still_useful(channel_T *channel)
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100309{
Bram Moolenaarfdd6ce42016-02-28 22:21:38 +0100310 int has_sock_msg;
Bram Moolenaarfdd6ce42016-02-28 22:21:38 +0100311 int has_out_msg;
312 int has_err_msg;
Bram Moolenaarfdd6ce42016-02-28 22:21:38 +0100313
314 /* If the job was killed the channel is not expected to work anymore. */
Bram Moolenaar46c85432016-02-26 11:17:46 +0100315 if (channel->ch_job_killed && channel->ch_job == NULL)
316 return FALSE;
Bram Moolenaarfdd6ce42016-02-28 22:21:38 +0100317
318 /* If there is a close callback it may still need to be invoked. */
319 if (channel->ch_close_cb != NULL)
320 return TRUE;
321
Bram Moolenaar5d96e3a2016-05-08 21:47:01 +0200322 /* If reading from or a buffer it's still useful. */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200323 if (channel->ch_part[PART_IN].ch_bufref.br_buf != NULL)
Bram Moolenaar5d96e3a2016-05-08 21:47:01 +0200324 return TRUE;
325
Bram Moolenaarfdd6ce42016-02-28 22:21:38 +0100326 /* If there is no callback then nobody can get readahead. If the fd is
327 * closed and there is no readahead then the callback won't be called. */
328 has_sock_msg = channel->ch_part[PART_SOCK].ch_fd != INVALID_FD
Bram Moolenaard23a8232018-02-10 18:45:26 +0100329 || channel->ch_part[PART_SOCK].ch_head.rq_next != NULL
330 || channel->ch_part[PART_SOCK].ch_json_head.jq_next != NULL;
Bram Moolenaarfdd6ce42016-02-28 22:21:38 +0100331 has_out_msg = channel->ch_part[PART_OUT].ch_fd != INVALID_FD
332 || channel->ch_part[PART_OUT].ch_head.rq_next != NULL
333 || channel->ch_part[PART_OUT].ch_json_head.jq_next != NULL;
334 has_err_msg = channel->ch_part[PART_ERR].ch_fd != INVALID_FD
335 || channel->ch_part[PART_ERR].ch_head.rq_next != NULL
336 || channel->ch_part[PART_ERR].ch_json_head.jq_next != NULL;
Bram Moolenaarfdd6ce42016-02-28 22:21:38 +0100337 return (channel->ch_callback != NULL && (has_sock_msg
Bram Moolenaar509ce2a2016-03-11 22:52:15 +0100338 || has_out_msg || has_err_msg))
Bram Moolenaar5d96e3a2016-05-08 21:47:01 +0200339 || ((channel->ch_part[PART_OUT].ch_callback != NULL
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200340 || channel->ch_part[PART_OUT].ch_bufref.br_buf != NULL)
341 && has_out_msg)
Bram Moolenaar5d96e3a2016-05-08 21:47:01 +0200342 || ((channel->ch_part[PART_ERR].ch_callback != NULL
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +0200343 || channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL)
344 && has_err_msg);
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100345}
346
347/*
Bram Moolenaar4e9d4432018-04-24 20:54:07 +0200348 * Return TRUE if "channel" is closeable (i.e. all readable fds are closed).
349 */
350 static int
351channel_can_close(channel_T *channel)
352{
353 return channel->ch_to_be_closed == 0;
354}
355
356/*
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200357 * Close a channel and free all its resources.
358 */
359 static void
360channel_free_contents(channel_T *channel)
361{
362 channel_close(channel, TRUE);
363 channel_clear(channel);
364 ch_log(channel, "Freeing channel");
365}
366
367 static void
368channel_free_channel(channel_T *channel)
369{
370 if (channel->ch_next != NULL)
371 channel->ch_next->ch_prev = channel->ch_prev;
372 if (channel->ch_prev == NULL)
373 first_channel = channel->ch_next;
374 else
375 channel->ch_prev->ch_next = channel->ch_next;
376 vim_free(channel);
377}
378
379 static void
380channel_free(channel_T *channel)
381{
382 if (!in_free_unref_items)
383 {
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +0200384 if (safe_to_invoke_callback == 0)
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +0200385 channel->ch_to_be_freed = TRUE;
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +0200386 else
387 {
388 channel_free_contents(channel);
389 channel_free_channel(channel);
390 }
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200391 }
392}
393
394/*
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100395 * Close a channel and free all its resources if there is no further action
Bram Moolenaar46c85432016-02-26 11:17:46 +0100396 * possible, there is no callback to be invoked or the associated job was
397 * killed.
Bram Moolenaar70765942016-02-28 19:28:59 +0100398 * Return TRUE if the channel was freed.
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100399 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100400 static int
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100401channel_may_free(channel_T *channel)
402{
Bram Moolenaar46c85432016-02-26 11:17:46 +0100403 if (!channel_still_useful(channel))
Bram Moolenaar70765942016-02-28 19:28:59 +0100404 {
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100405 channel_free(channel);
Bram Moolenaar70765942016-02-28 19:28:59 +0100406 return TRUE;
407 }
408 return FALSE;
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +0100409}
410
411/*
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100412 * Decrement the reference count on "channel" and maybe free it when it goes
413 * down to zero. Don't free it if there is a pending action.
414 * Returns TRUE when the channel is no longer referenced.
415 */
416 int
417channel_unref(channel_T *channel)
418{
419 if (channel != NULL && --channel->ch_refcount <= 0)
420 return channel_may_free(channel);
421 return FALSE;
422}
423
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200424 int
425free_unused_channels_contents(int copyID, int mask)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100426{
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200427 int did_free = FALSE;
428 channel_T *ch;
429
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +0200430 /* This is invoked from the garbage collector, which only runs at a safe
431 * point. */
432 ++safe_to_invoke_callback;
433
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200434 for (ch = first_channel; ch != NULL; ch = ch->ch_next)
Bram Moolenaar674127e2016-04-26 20:30:07 +0200435 if (!channel_still_useful(ch)
436 && (ch->ch_copyID & mask) != (copyID & mask))
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200437 {
438 /* Free the channel and ordinary items it contains, but don't
439 * recurse into Lists, Dictionaries etc. */
440 channel_free_contents(ch);
441 did_free = TRUE;
442 }
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +0200443
444 --safe_to_invoke_callback;
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200445 return did_free;
446}
447
448 void
449free_unused_channels(int copyID, int mask)
450{
451 channel_T *ch;
452 channel_T *ch_next;
453
454 for (ch = first_channel; ch != NULL; ch = ch_next)
455 {
456 ch_next = ch->ch_next;
Bram Moolenaar674127e2016-04-26 20:30:07 +0200457 if (!channel_still_useful(ch)
458 && (ch->ch_copyID & mask) != (copyID & mask))
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200459 {
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +0200460 /* Free the channel struct itself. */
Bram Moolenaar107e1ee2016-04-08 17:07:19 +0200461 channel_free_channel(ch);
462 }
463 }
Bram Moolenaare0874f82016-01-24 20:36:41 +0100464}
465
Bram Moolenaard04a0202016-01-26 23:30:18 +0100466#if defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaar77073442016-02-13 23:23:53 +0100467
468#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
469 static void
Bram Moolenaarfffd5562016-02-20 18:44:39 +0100470channel_read_fd(int fd)
Bram Moolenaar77073442016-02-13 23:23:53 +0100471{
Bram Moolenaarfffd5562016-02-20 18:44:39 +0100472 channel_T *channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200473 ch_part_T part;
Bram Moolenaar77073442016-02-13 23:23:53 +0100474
Bram Moolenaarfffd5562016-02-20 18:44:39 +0100475 channel = channel_fd2channel(fd, &part);
Bram Moolenaar77073442016-02-13 23:23:53 +0100476 if (channel == NULL)
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200477 ch_error(NULL, "Channel for fd %d not found", fd);
Bram Moolenaar77073442016-02-13 23:23:53 +0100478 else
Bram Moolenaarf8df45d2016-05-25 21:48:13 +0200479 channel_read(channel, part, "channel_read_fd");
Bram Moolenaar77073442016-02-13 23:23:53 +0100480}
481#endif
482
Bram Moolenaare0874f82016-01-24 20:36:41 +0100483/*
Bram Moolenaard04a0202016-01-26 23:30:18 +0100484 * Read a command from netbeans.
Bram Moolenaare0874f82016-01-24 20:36:41 +0100485 */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100486#ifdef FEAT_GUI_X11
487 static void
Bram Moolenaarf8df45d2016-05-25 21:48:13 +0200488messageFromServer(XtPointer clientData,
489 int *unused1 UNUSED,
490 XtInputId *unused2 UNUSED)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100491{
Bram Moolenaarfffd5562016-02-20 18:44:39 +0100492 channel_read_fd((int)(long)clientData);
Bram Moolenaare0874f82016-01-24 20:36:41 +0100493}
Bram Moolenaard04a0202016-01-26 23:30:18 +0100494#endif
Bram Moolenaare0874f82016-01-24 20:36:41 +0100495
Bram Moolenaard04a0202016-01-26 23:30:18 +0100496#ifdef FEAT_GUI_GTK
Bram Moolenaar98921892016-02-23 17:14:37 +0100497# if GTK_CHECK_VERSION(3,0,0)
498 static gboolean
Bram Moolenaarf8df45d2016-05-25 21:48:13 +0200499messageFromServer(GIOChannel *unused1 UNUSED,
500 GIOCondition unused2 UNUSED,
501 gpointer clientData)
Bram Moolenaar98921892016-02-23 17:14:37 +0100502{
503 channel_read_fd(GPOINTER_TO_INT(clientData));
504 return TRUE; /* Return FALSE instead in case the event source is to
505 * be removed after this function returns. */
506}
507# else
Bram Moolenaard04a0202016-01-26 23:30:18 +0100508 static void
Bram Moolenaarf8df45d2016-05-25 21:48:13 +0200509messageFromServer(gpointer clientData,
510 gint unused1 UNUSED,
511 GdkInputCondition unused2 UNUSED)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100512{
Bram Moolenaarfffd5562016-02-20 18:44:39 +0100513 channel_read_fd((int)(long)clientData);
Bram Moolenaare0874f82016-01-24 20:36:41 +0100514}
Bram Moolenaar98921892016-02-23 17:14:37 +0100515# endif
Bram Moolenaare0874f82016-01-24 20:36:41 +0100516#endif
517
518 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200519channel_gui_register_one(channel_T *channel, ch_part_T part)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100520{
Bram Moolenaarde279892016-03-11 22:19:44 +0100521 if (!CH_HAS_GUI)
522 return;
523
Bram Moolenaar13ebb032017-08-26 22:02:51 +0200524 /* gets stuck in handling events for a not connected channel */
525 if (channel->ch_keep_open)
526 return;
527
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100528# ifdef FEAT_GUI_X11
529 /* Tell notifier we are interested in being called
530 * when there is input on the editor connection socket. */
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100531 if (channel->ch_part[part].ch_inputHandler == (XtInputId)NULL)
532 channel->ch_part[part].ch_inputHandler = XtAppAddInput(
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100533 (XtAppContext)app_context,
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100534 channel->ch_part[part].ch_fd,
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100535 (XtPointer)(XtInputReadMask + XtInputExceptMask),
Bram Moolenaarf8df45d2016-05-25 21:48:13 +0200536 messageFromServer,
Bram Moolenaarfffd5562016-02-20 18:44:39 +0100537 (XtPointer)(long)channel->ch_part[part].ch_fd);
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100538# else
539# ifdef FEAT_GUI_GTK
540 /* Tell gdk we are interested in being called when there
541 * is input on the editor connection socket. */
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100542 if (channel->ch_part[part].ch_inputHandler == 0)
Bram Moolenaar98921892016-02-23 17:14:37 +0100543# if GTK_CHECK_VERSION(3,0,0)
544 {
545 GIOChannel *chnnl = g_io_channel_unix_new(
546 (gint)channel->ch_part[part].ch_fd);
547
548 channel->ch_part[part].ch_inputHandler = g_io_add_watch(
549 chnnl,
550 G_IO_IN|G_IO_HUP|G_IO_ERR|G_IO_PRI,
Bram Moolenaarf8df45d2016-05-25 21:48:13 +0200551 messageFromServer,
Bram Moolenaar98921892016-02-23 17:14:37 +0100552 GINT_TO_POINTER(channel->ch_part[part].ch_fd));
553
554 g_io_channel_unref(chnnl);
555 }
556# else
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100557 channel->ch_part[part].ch_inputHandler = gdk_input_add(
558 (gint)channel->ch_part[part].ch_fd,
Bram Moolenaar16eb4f82016-02-14 23:02:34 +0100559 (GdkInputCondition)
560 ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
Bram Moolenaarf8df45d2016-05-25 21:48:13 +0200561 messageFromServer,
Bram Moolenaarfffd5562016-02-20 18:44:39 +0100562 (gpointer)(long)channel->ch_part[part].ch_fd);
Bram Moolenaar98921892016-02-23 17:14:37 +0100563# endif
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100564# endif
565# endif
566}
567
Bram Moolenaarde279892016-03-11 22:19:44 +0100568 static void
Bram Moolenaar77073442016-02-13 23:23:53 +0100569channel_gui_register(channel_T *channel)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100570{
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100571 if (channel->CH_SOCK_FD != INVALID_FD)
572 channel_gui_register_one(channel, PART_SOCK);
Bram Moolenaar13ebb032017-08-26 22:02:51 +0200573 if (channel->CH_OUT_FD != INVALID_FD
574 && channel->CH_OUT_FD != channel->CH_SOCK_FD)
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100575 channel_gui_register_one(channel, PART_OUT);
Bram Moolenaar13ebb032017-08-26 22:02:51 +0200576 if (channel->CH_ERR_FD != INVALID_FD
577 && channel->CH_ERR_FD != channel->CH_SOCK_FD
578 && channel->CH_ERR_FD != channel->CH_OUT_FD)
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100579 channel_gui_register_one(channel, PART_ERR);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100580}
581
582/*
583 * Register any of our file descriptors with the GUI event handling system.
584 * Called when the GUI has started.
585 */
586 void
587channel_gui_register_all(void)
588{
Bram Moolenaar77073442016-02-13 23:23:53 +0100589 channel_T *channel;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100590
Bram Moolenaar77073442016-02-13 23:23:53 +0100591 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100592 channel_gui_register(channel);
593}
594
595 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200596channel_gui_unregister_one(channel_T *channel, ch_part_T part)
Bram Moolenaarde279892016-03-11 22:19:44 +0100597{
598# ifdef FEAT_GUI_X11
599 if (channel->ch_part[part].ch_inputHandler != (XtInputId)NULL)
600 {
601 XtRemoveInput(channel->ch_part[part].ch_inputHandler);
602 channel->ch_part[part].ch_inputHandler = (XtInputId)NULL;
603 }
604# else
605# ifdef FEAT_GUI_GTK
606 if (channel->ch_part[part].ch_inputHandler != 0)
607 {
608# if GTK_CHECK_VERSION(3,0,0)
609 g_source_remove(channel->ch_part[part].ch_inputHandler);
610# else
611 gdk_input_remove(channel->ch_part[part].ch_inputHandler);
612# endif
613 channel->ch_part[part].ch_inputHandler = 0;
614 }
615# endif
616# endif
617}
618
619 static void
Bram Moolenaar16eb4f82016-02-14 23:02:34 +0100620channel_gui_unregister(channel_T *channel)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100621{
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200622 ch_part_T part;
Bram Moolenaar16eb4f82016-02-14 23:02:34 +0100623
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100624 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaarde279892016-03-11 22:19:44 +0100625 channel_gui_unregister_one(channel, part);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100626}
627
628#endif
629
Bram Moolenaare74e8e72016-02-16 22:01:30 +0100630static char *e_cannot_connect = N_("E902: Cannot connect to port");
631
Bram Moolenaard04a0202016-01-26 23:30:18 +0100632/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100633 * Open a socket channel to "hostname":"port".
Bram Moolenaare74e8e72016-02-16 22:01:30 +0100634 * "waittime" is the time in msec to wait for the connection.
635 * When negative wait forever.
Bram Moolenaar77073442016-02-13 23:23:53 +0100636 * Returns the channel for success.
637 * Returns NULL for failure.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100638 */
Bram Moolenaar77073442016-02-13 23:23:53 +0100639 channel_T *
Bram Moolenaar4e221c92016-02-23 13:20:22 +0100640channel_open(
641 char *hostname,
642 int port_in,
643 int waittime,
644 void (*nb_close_cb)(void))
Bram Moolenaard04a0202016-01-26 23:30:18 +0100645{
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100646 int sd = -1;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100647 struct sockaddr_in server;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100648 struct hostent *host;
Bram Moolenaarf12d9832016-01-29 21:11:25 +0100649#ifdef WIN32
Bram Moolenaard04a0202016-01-26 23:30:18 +0100650 u_short port = port_in;
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100651 u_long val = 1;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100652#else
653 int port = port_in;
654#endif
Bram Moolenaar77073442016-02-13 23:23:53 +0100655 channel_T *channel;
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100656 int ret;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100657
Bram Moolenaarf12d9832016-01-29 21:11:25 +0100658#ifdef WIN32
Bram Moolenaard04a0202016-01-26 23:30:18 +0100659 channel_init_winsock();
660#endif
661
Bram Moolenaar77073442016-02-13 23:23:53 +0100662 channel = add_channel();
663 if (channel == NULL)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100664 {
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100665 ch_error(NULL, "Cannot allocate channel.");
Bram Moolenaar77073442016-02-13 23:23:53 +0100666 return NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100667 }
668
669 /* Get the server internet address and put into addr structure */
670 /* fill in the socket address structure and connect to server */
671 vim_memset((char *)&server, 0, sizeof(server));
672 server.sin_family = AF_INET;
673 server.sin_port = htons(port);
674 if ((host = gethostbyname(hostname)) == NULL)
675 {
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100676 ch_error(channel, "in gethostbyname() in channel_open()");
Bram Moolenaar5b302912016-08-24 22:11:55 +0200677 PERROR(_("E901: gethostbyname() in channel_open()"));
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100678 channel_free(channel);
Bram Moolenaar77073442016-02-13 23:23:53 +0100679 return NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100680 }
Bram Moolenaar7173b472017-01-14 17:04:38 +0100681 {
682 char *p;
683
Bram Moolenaar2e324952018-04-14 14:37:07 +0200684 /* When using host->h_addr_list[0] directly ubsan warns for it to not
685 * be aligned. First copy the pointer to avoid that. */
686 memcpy(&p, &host->h_addr_list[0], sizeof(p));
Bram Moolenaar7173b472017-01-14 17:04:38 +0100687 memcpy((char *)&server.sin_addr, p, host->h_length);
688 }
Bram Moolenaard04a0202016-01-26 23:30:18 +0100689
Bram Moolenaar254e00d2016-02-19 23:23:12 +0100690 /* On Mac and Solaris a zero timeout almost never works. At least wait
691 * one millisecond. Let's do it for all systems, because we don't know why
692 * this is needed. */
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100693 if (waittime == 0)
694 waittime = 1;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100695
696 /*
697 * For Unix we need to call connect() again after connect() failed.
698 * On Win32 one time is sufficient.
699 */
700 while (TRUE)
701 {
Bram Moolenaar562ca712016-03-09 21:50:05 +0100702 long elapsed_msec = 0;
703 int waitnow;
Bram Moolenaar045a2842016-03-08 22:33:07 +0100704
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100705 if (sd >= 0)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100706 sock_close(sd);
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100707 sd = socket(AF_INET, SOCK_STREAM, 0);
708 if (sd == -1)
709 {
710 ch_error(channel, "in socket() in channel_open().");
Bram Moolenaar5b302912016-08-24 22:11:55 +0200711 PERROR(_("E898: socket() in channel_open()"));
Bram Moolenaar7b3ca762016-02-14 19:13:43 +0100712 channel_free(channel);
Bram Moolenaar77073442016-02-13 23:23:53 +0100713 return NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100714 }
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100715
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100716 if (waittime >= 0)
717 {
718 /* Make connect() non-blocking. */
719 if (
720#ifdef _WIN32
721 ioctlsocket(sd, FIONBIO, &val) < 0
722#else
723 fcntl(sd, F_SETFL, O_NONBLOCK) < 0
724#endif
725 )
726 {
727 SOCK_ERRNO;
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200728 ch_error(channel,
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100729 "channel_open: Connect failed with errno %d", errno);
730 sock_close(sd);
731 channel_free(channel);
732 return NULL;
733 }
734 }
735
736 /* Try connecting to the server. */
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200737 ch_log(channel, "Connecting to %s port %d", hostname, port);
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100738 ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
739
Bram Moolenaar045a2842016-03-08 22:33:07 +0100740 if (ret == 0)
741 /* The connection could be established. */
742 break;
743
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100744 SOCK_ERRNO;
Bram Moolenaar045a2842016-03-08 22:33:07 +0100745 if (waittime < 0 || (errno != EWOULDBLOCK
746 && errno != ECONNREFUSED
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100747#ifdef EINPROGRESS
Bram Moolenaar045a2842016-03-08 22:33:07 +0100748 && errno != EINPROGRESS
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100749#endif
Bram Moolenaar045a2842016-03-08 22:33:07 +0100750 ))
751 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200752 ch_error(channel,
Bram Moolenaar045a2842016-03-08 22:33:07 +0100753 "channel_open: Connect failed with errno %d", errno);
754 PERROR(_(e_cannot_connect));
755 sock_close(sd);
756 channel_free(channel);
757 return NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100758 }
Bram Moolenaard04a0202016-01-26 23:30:18 +0100759
Bram Moolenaar40e8cb22016-03-10 21:10:58 +0100760 /* Limit the waittime to 50 msec. If it doesn't work within this
761 * time we close the socket and try creating it again. */
762 waitnow = waittime > 50 ? 50 : waittime;
763
Bram Moolenaar045a2842016-03-08 22:33:07 +0100764 /* If connect() didn't finish then try using select() to wait for the
Bram Moolenaar562ca712016-03-09 21:50:05 +0100765 * connection to be made. For Win32 always use select() to wait. */
Bram Moolenaar045a2842016-03-08 22:33:07 +0100766#ifndef WIN32
767 if (errno != ECONNREFUSED)
768#endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100769 {
770 struct timeval tv;
Bram Moolenaard42119f2016-02-28 20:51:49 +0100771 fd_set rfds;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100772 fd_set wfds;
Bram Moolenaare081e212016-02-28 22:33:46 +0100773#ifndef WIN32
Bram Moolenaard42119f2016-02-28 20:51:49 +0100774 int so_error = 0;
775 socklen_t so_error_len = sizeof(so_error);
Bram Moolenaar045a2842016-03-08 22:33:07 +0100776 struct timeval start_tv;
777 struct timeval end_tv;
Bram Moolenaare081e212016-02-28 22:33:46 +0100778#endif
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100779 FD_ZERO(&rfds);
780 FD_SET(sd, &rfds);
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100781 FD_ZERO(&wfds);
782 FD_SET(sd, &wfds);
Bram Moolenaare74e8e72016-02-16 22:01:30 +0100783
Bram Moolenaar562ca712016-03-09 21:50:05 +0100784 tv.tv_sec = waitnow / 1000;
785 tv.tv_usec = (waitnow % 1000) * 1000;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100786#ifndef WIN32
787 gettimeofday(&start_tv, NULL);
788#endif
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200789 ch_log(channel,
Bram Moolenaar562ca712016-03-09 21:50:05 +0100790 "Waiting for connection (waiting %d msec)...", waitnow);
Bram Moolenaard42119f2016-02-28 20:51:49 +0100791 ret = select((int)sd + 1, &rfds, &wfds, NULL, &tv);
Bram Moolenaare74e8e72016-02-16 22:01:30 +0100792
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100793 if (ret < 0)
794 {
795 SOCK_ERRNO;
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200796 ch_error(channel,
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100797 "channel_open: Connect failed with errno %d", errno);
798 PERROR(_(e_cannot_connect));
799 sock_close(sd);
800 channel_free(channel);
801 return NULL;
802 }
Bram Moolenaard42119f2016-02-28 20:51:49 +0100803
Bram Moolenaare081e212016-02-28 22:33:46 +0100804#ifdef WIN32
Bram Moolenaar562ca712016-03-09 21:50:05 +0100805 /* On Win32: select() is expected to work and wait for up to
806 * "waitnow" msec for the socket to be open. */
Bram Moolenaar045a2842016-03-08 22:33:07 +0100807 if (FD_ISSET(sd, &wfds))
808 break;
Bram Moolenaar562ca712016-03-09 21:50:05 +0100809 elapsed_msec = waitnow;
810 if (waittime > 1 && elapsed_msec < waittime)
811 {
812 waittime -= elapsed_msec;
813 continue;
814 }
Bram Moolenaare081e212016-02-28 22:33:46 +0100815#else
816 /* On Linux-like systems: See socket(7) for the behavior
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100817 * After putting the socket in non-blocking mode, connect() will
818 * return EINPROGRESS, select() will not wait (as if writing is
819 * possible), need to use getsockopt() to check if the socket is
Bram Moolenaar42bc6dd2016-03-02 20:48:47 +0100820 * actually able to connect.
Bram Moolenaar045a2842016-03-08 22:33:07 +0100821 * We detect a failure to connect when either read and write fds
Bram Moolenaard42119f2016-02-28 20:51:49 +0100822 * are set. Use getsockopt() to find out what kind of failure. */
Bram Moolenaar42bc6dd2016-03-02 20:48:47 +0100823 if (FD_ISSET(sd, &rfds) || FD_ISSET(sd, &wfds))
Bram Moolenaard42119f2016-02-28 20:51:49 +0100824 {
825 ret = getsockopt(sd,
Bram Moolenaar045a2842016-03-08 22:33:07 +0100826 SOL_SOCKET, SO_ERROR, &so_error, &so_error_len);
Bram Moolenaard42119f2016-02-28 20:51:49 +0100827 if (ret < 0 || (so_error != 0
828 && so_error != EWOULDBLOCK
829 && so_error != ECONNREFUSED
Bram Moolenaare081e212016-02-28 22:33:46 +0100830# ifdef EINPROGRESS
Bram Moolenaard42119f2016-02-28 20:51:49 +0100831 && so_error != EINPROGRESS
Bram Moolenaare081e212016-02-28 22:33:46 +0100832# endif
Bram Moolenaard42119f2016-02-28 20:51:49 +0100833 ))
834 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +0200835 ch_error(channel,
Bram Moolenaard42119f2016-02-28 20:51:49 +0100836 "channel_open: Connect failed with errno %d",
837 so_error);
838 PERROR(_(e_cannot_connect));
839 sock_close(sd);
840 channel_free(channel);
841 return NULL;
842 }
843 }
844
Bram Moolenaar045a2842016-03-08 22:33:07 +0100845 if (FD_ISSET(sd, &wfds) && so_error == 0)
846 /* Did not detect an error, connection is established. */
847 break;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100848
Bram Moolenaar045a2842016-03-08 22:33:07 +0100849 gettimeofday(&end_tv, NULL);
850 elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000
851 + (end_tv.tv_usec - start_tv.tv_usec) / 1000;
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100852#endif
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100853 }
Bram Moolenaar045a2842016-03-08 22:33:07 +0100854
855#ifndef WIN32
856 if (waittime > 1 && elapsed_msec < waittime)
857 {
858 /* The port isn't ready but we also didn't get an error.
859 * This happens when the server didn't open the socket
Bram Moolenaar562ca712016-03-09 21:50:05 +0100860 * yet. Select() may return early, wait until the remaining
861 * "waitnow" and try again. */
862 waitnow -= elapsed_msec;
863 waittime -= elapsed_msec;
864 if (waitnow > 0)
865 {
866 mch_delay((long)waitnow, TRUE);
867 ui_breakcheck();
868 waittime -= waitnow;
869 }
Bram Moolenaar045a2842016-03-08 22:33:07 +0100870 if (!got_int)
871 {
Bram Moolenaar562ca712016-03-09 21:50:05 +0100872 if (waittime <= 0)
873 /* give it one more try */
Bram Moolenaar045a2842016-03-08 22:33:07 +0100874 waittime = 1;
875 continue;
876 }
877 /* we were interrupted, behave as if timed out */
878 }
879#endif
880
881 /* We timed out. */
882 ch_error(channel, "Connection timed out");
883 sock_close(sd);
884 channel_free(channel);
885 return NULL;
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100886 }
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100887
Bram Moolenaar045a2842016-03-08 22:33:07 +0100888 ch_log(channel, "Connection made");
889
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100890 if (waittime >= 0)
891 {
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100892#ifdef _WIN32
893 val = 0;
894 ioctlsocket(sd, FIONBIO, &val);
895#else
Bram Moolenaarfbc4b4d2016-02-07 15:14:01 +0100896 (void)fcntl(sd, F_SETFL, 0);
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100897#endif
898 }
899
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100900 channel->CH_SOCK_FD = (sock_T)sd;
Bram Moolenaar4e221c92016-02-23 13:20:22 +0100901 channel->ch_nb_close_cb = nb_close_cb;
Bram Moolenaar03602ec2016-03-20 20:57:45 +0100902 channel->ch_hostname = (char *)vim_strsave((char_u *)hostname);
903 channel->ch_port = port_in;
Bram Moolenaar4e9d4432018-04-24 20:54:07 +0200904 channel->ch_to_be_closed |= (1U << PART_SOCK);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100905
906#ifdef FEAT_GUI
Bram Moolenaarde279892016-03-11 22:19:44 +0100907 channel_gui_register_one(channel, PART_SOCK);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100908#endif
909
Bram Moolenaar77073442016-02-13 23:23:53 +0100910 return channel;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100911}
912
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100913/*
914 * Implements ch_open().
915 */
916 channel_T *
917channel_open_func(typval_T *argvars)
918{
919 char_u *address;
920 char_u *p;
921 char *rest;
922 int port;
923 jobopt_T opt;
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +0200924 channel_T *channel = NULL;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100925
926 address = get_tv_string(&argvars[0]);
927 if (argvars[1].v_type != VAR_UNKNOWN
928 && (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL))
929 {
930 EMSG(_(e_invarg));
931 return NULL;
932 }
933
934 /* parse address */
935 p = vim_strchr(address, ':');
936 if (p == NULL)
937 {
938 EMSG2(_(e_invarg2), address);
939 return NULL;
940 }
941 *p++ = NUL;
942 port = strtol((char *)p, &rest, 10);
943 if (*address == NUL || port <= 0 || *rest != NUL)
944 {
945 p[-1] = ':';
946 EMSG2(_(e_invarg2), address);
947 return NULL;
948 }
949
950 /* parse options */
951 clear_job_options(&opt);
952 opt.jo_mode = MODE_JSON;
953 opt.jo_timeout = 2000;
954 if (get_job_options(&argvars[1], &opt,
Bram Moolenaar08d384f2017-08-11 21:51:23 +0200955 JO_MODE_ALL + JO_CB_ALL + JO_WAITTIME + JO_TIMEOUT_ALL, 0) == FAIL)
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +0200956 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100957 if (opt.jo_timeout < 0)
958 {
959 EMSG(_(e_invarg));
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +0200960 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100961 }
962
963 channel = channel_open((char *)address, port, opt.jo_waittime, NULL);
964 if (channel != NULL)
965 {
966 opt.jo_set = JO_ALL;
967 channel_set_options(channel, &opt);
968 }
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +0200969theend:
970 free_job_options(&opt);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +0100971 return channel;
972}
973
Bram Moolenaarde279892016-03-11 22:19:44 +0100974 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200975ch_close_part(channel_T *channel, ch_part_T part)
Bram Moolenaarde279892016-03-11 22:19:44 +0100976{
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200977 sock_T *fd = &channel->ch_part[part].ch_fd;
978
Bram Moolenaarde279892016-03-11 22:19:44 +0100979 if (*fd != INVALID_FD)
980 {
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200981 if (part == PART_SOCK)
982 sock_close(*fd);
983 else
Bram Moolenaar5a1feb82017-07-22 18:04:08 +0200984 {
985 /* When using a pty the same FD is set on multiple parts, only
986 * close it when the last reference is closed. */
Bram Moolenaar7c9aec42017-08-03 13:51:25 +0200987 if ((part == PART_IN || channel->CH_IN_FD != *fd)
988 && (part == PART_OUT || channel->CH_OUT_FD != *fd)
989 && (part == PART_ERR || channel->CH_ERR_FD != *fd))
Bram Moolenaar2dc9d262017-09-08 14:39:30 +0200990 {
991#ifdef WIN32
992 if (channel->ch_named_pipe)
993 DisconnectNamedPipe((HANDLE)fd);
994#endif
Bram Moolenaar5a1feb82017-07-22 18:04:08 +0200995 fd_close(*fd);
Bram Moolenaar2dc9d262017-09-08 14:39:30 +0200996 }
Bram Moolenaar5a1feb82017-07-22 18:04:08 +0200997 }
Bram Moolenaarde279892016-03-11 22:19:44 +0100998 *fd = INVALID_FD;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +0200999
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02001000 /* channel is closed, may want to end the job if it was the last */
1001 channel->ch_to_be_closed &= ~(1U << part);
Bram Moolenaarde279892016-03-11 22:19:44 +01001002 }
1003}
1004
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001005 void
Bram Moolenaard8070362016-02-15 21:56:54 +01001006channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001007{
Bram Moolenaarde279892016-03-11 22:19:44 +01001008 if (in != INVALID_FD)
1009 {
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001010 ch_close_part(channel, PART_IN);
Bram Moolenaarde279892016-03-11 22:19:44 +01001011 channel->CH_IN_FD = in;
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02001012# if defined(UNIX)
1013 /* Do not end the job when all output channels are closed, wait until
1014 * the job ended. */
1015 if (isatty(in))
1016 channel->ch_to_be_closed |= (1U << PART_IN);
1017# endif
Bram Moolenaarde279892016-03-11 22:19:44 +01001018 }
1019 if (out != INVALID_FD)
1020 {
1021# if defined(FEAT_GUI)
1022 channel_gui_unregister_one(channel, PART_OUT);
1023# endif
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001024 ch_close_part(channel, PART_OUT);
Bram Moolenaarde279892016-03-11 22:19:44 +01001025 channel->CH_OUT_FD = out;
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02001026 channel->ch_to_be_closed |= (1U << PART_OUT);
Bram Moolenaarde279892016-03-11 22:19:44 +01001027# if defined(FEAT_GUI)
1028 channel_gui_register_one(channel, PART_OUT);
1029# endif
1030 }
1031 if (err != INVALID_FD)
1032 {
1033# if defined(FEAT_GUI)
1034 channel_gui_unregister_one(channel, PART_ERR);
1035# endif
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001036 ch_close_part(channel, PART_ERR);
Bram Moolenaarde279892016-03-11 22:19:44 +01001037 channel->CH_ERR_FD = err;
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02001038 channel->ch_to_be_closed |= (1U << PART_ERR);
Bram Moolenaarde279892016-03-11 22:19:44 +01001039# if defined(FEAT_GUI)
1040 channel_gui_register_one(channel, PART_ERR);
1041# endif
1042 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001043}
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001044
Bram Moolenaard6051b52016-02-28 15:49:03 +01001045/*
Bram Moolenaar014069a2016-03-03 22:51:40 +01001046 * Sets the job the channel is associated with and associated options.
Bram Moolenaard6051b52016-02-28 15:49:03 +01001047 * This does not keep a refcount, when the job is freed ch_job is cleared.
1048 */
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001049 void
Bram Moolenaar014069a2016-03-03 22:51:40 +01001050channel_set_job(channel_T *channel, job_T *job, jobopt_T *options)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001051{
Bram Moolenaar77073442016-02-13 23:23:53 +01001052 channel->ch_job = job;
Bram Moolenaar014069a2016-03-03 22:51:40 +01001053
1054 channel_set_options(channel, options);
1055
1056 if (job->jv_in_buf != NULL)
1057 {
1058 chanpart_T *in_part = &channel->ch_part[PART_IN];
1059
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001060 set_bufref(&in_part->ch_bufref, job->jv_in_buf);
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001061 ch_log(channel, "reading from buffer '%s'",
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001062 (char *)in_part->ch_bufref.br_buf->b_ffname);
Bram Moolenaar014069a2016-03-03 22:51:40 +01001063 if (options->jo_set & JO_IN_TOP)
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001064 {
1065 if (options->jo_in_top == 0 && !(options->jo_set & JO_IN_BOT))
1066 {
1067 /* Special mode: send last-but-one line when appending a line
1068 * to the buffer. */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001069 in_part->ch_bufref.br_buf->b_write_to_channel = TRUE;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001070 in_part->ch_buf_append = TRUE;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001071 in_part->ch_buf_top =
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001072 in_part->ch_bufref.br_buf->b_ml.ml_line_count + 1;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001073 }
1074 else
1075 in_part->ch_buf_top = options->jo_in_top;
1076 }
Bram Moolenaar014069a2016-03-03 22:51:40 +01001077 else
1078 in_part->ch_buf_top = 1;
1079 if (options->jo_set & JO_IN_BOT)
1080 in_part->ch_buf_bot = options->jo_in_bot;
1081 else
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001082 in_part->ch_buf_bot = in_part->ch_bufref.br_buf->b_ml.ml_line_count;
Bram Moolenaar014069a2016-03-03 22:51:40 +01001083 }
Bram Moolenaard04a0202016-01-26 23:30:18 +01001084}
1085
1086/*
Bram Moolenaar187db502016-02-27 14:44:26 +01001087 * Find a buffer matching "name" or create a new one.
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001088 * Returns NULL if there is something very wrong (error already reported).
Bram Moolenaar187db502016-02-27 14:44:26 +01001089 */
1090 static buf_T *
Bram Moolenaar169ebb02016-09-07 23:32:23 +02001091find_buffer(char_u *name, int err, int msg)
Bram Moolenaar187db502016-02-27 14:44:26 +01001092{
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01001093 buf_T *buf = NULL;
Bram Moolenaar187db502016-02-27 14:44:26 +01001094 buf_T *save_curbuf = curbuf;
1095
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01001096 if (name != NULL && *name != NUL)
Bram Moolenaarb127cfd2016-05-29 16:24:50 +02001097 {
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01001098 buf = buflist_findname(name);
Bram Moolenaarb127cfd2016-05-29 16:24:50 +02001099 if (buf == NULL)
1100 buf = buflist_findname_exp(name);
1101 }
Bram Moolenaar187db502016-02-27 14:44:26 +01001102 if (buf == NULL)
1103 {
Bram Moolenaare26643e2016-02-27 21:53:02 +01001104 buf = buflist_new(name == NULL || *name == NUL ? NULL : name,
Bram Moolenaarb127cfd2016-05-29 16:24:50 +02001105 NULL, (linenr_T)0, BLN_LISTED | BLN_NEW);
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001106 if (buf == NULL)
1107 return NULL;
Bram Moolenaar187db502016-02-27 14:44:26 +01001108 buf_copy_options(buf, BCO_ENTER);
Bram Moolenaara4f6ca72016-03-20 17:28:35 +01001109 curbuf = buf;
Bram Moolenaar187db502016-02-27 14:44:26 +01001110#ifdef FEAT_QUICKFIX
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001111 set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL);
1112 set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL);
Bram Moolenaar187db502016-02-27 14:44:26 +01001113#endif
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001114 if (curbuf->b_ml.ml_mfp == NULL)
1115 ml_open(curbuf);
Bram Moolenaar169ebb02016-09-07 23:32:23 +02001116 if (msg)
1117 ml_replace(1, (char_u *)(err ? "Reading from channel error..."
Bram Moolenaar6ff02c92016-03-08 20:12:44 +01001118 : "Reading from channel output..."), TRUE);
Bram Moolenaar187db502016-02-27 14:44:26 +01001119 changed_bytes(1, 0);
1120 curbuf = save_curbuf;
1121 }
1122
1123 return buf;
1124}
1125
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02001126 static void
1127set_callback(
1128 char_u **cbp,
1129 partial_T **pp,
1130 char_u *callback,
1131 partial_T *partial)
1132{
1133 free_callback(*cbp, *pp);
1134 if (callback != NULL && *callback != NUL)
Bram Moolenaar5ef2e762016-07-15 21:29:35 +02001135 {
1136 if (partial != NULL)
Bram Moolenaar437bafe2016-08-01 15:40:54 +02001137 *cbp = partial_name(partial);
Bram Moolenaar5ef2e762016-07-15 21:29:35 +02001138 else
Bram Moolenaar437bafe2016-08-01 15:40:54 +02001139 {
Bram Moolenaar5ef2e762016-07-15 21:29:35 +02001140 *cbp = vim_strsave(callback);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02001141 func_ref(*cbp);
1142 }
Bram Moolenaar5ef2e762016-07-15 21:29:35 +02001143 }
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02001144 else
1145 *cbp = NULL;
1146 *pp = partial;
Bram Moolenaar437bafe2016-08-01 15:40:54 +02001147 if (partial != NULL)
1148 ++partial->pt_refcount;
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02001149}
1150
Bram Moolenaar187db502016-02-27 14:44:26 +01001151/*
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001152 * Set various properties from an "opt" argument.
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001153 */
1154 void
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001155channel_set_options(channel_T *channel, jobopt_T *opt)
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001156{
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001157 ch_part_T part;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001158
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001159 if (opt->jo_set & JO_MODE)
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001160 for (part = PART_SOCK; part < PART_COUNT; ++part)
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001161 channel->ch_part[part].ch_mode = opt->jo_mode;
1162 if (opt->jo_set & JO_IN_MODE)
1163 channel->ch_part[PART_IN].ch_mode = opt->jo_in_mode;
1164 if (opt->jo_set & JO_OUT_MODE)
1165 channel->ch_part[PART_OUT].ch_mode = opt->jo_out_mode;
1166 if (opt->jo_set & JO_ERR_MODE)
1167 channel->ch_part[PART_ERR].ch_mode = opt->jo_err_mode;
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001168
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001169 if (opt->jo_set & JO_TIMEOUT)
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001170 for (part = PART_SOCK; part < PART_COUNT; ++part)
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001171 channel->ch_part[part].ch_timeout = opt->jo_timeout;
1172 if (opt->jo_set & JO_OUT_TIMEOUT)
1173 channel->ch_part[PART_OUT].ch_timeout = opt->jo_out_timeout;
1174 if (opt->jo_set & JO_ERR_TIMEOUT)
1175 channel->ch_part[PART_ERR].ch_timeout = opt->jo_err_timeout;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001176 if (opt->jo_set & JO_BLOCK_WRITE)
1177 channel->ch_part[PART_IN].ch_block_write = 1;
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001178
1179 if (opt->jo_set & JO_CALLBACK)
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02001180 set_callback(&channel->ch_callback, &channel->ch_partial,
1181 opt->jo_callback, opt->jo_partial);
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001182 if (opt->jo_set & JO_OUT_CALLBACK)
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02001183 set_callback(&channel->ch_part[PART_OUT].ch_callback,
1184 &channel->ch_part[PART_OUT].ch_partial,
1185 opt->jo_out_cb, opt->jo_out_partial);
Bram Moolenaarb6b52522016-02-20 23:30:07 +01001186 if (opt->jo_set & JO_ERR_CALLBACK)
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02001187 set_callback(&channel->ch_part[PART_ERR].ch_callback,
1188 &channel->ch_part[PART_ERR].ch_partial,
1189 opt->jo_err_cb, opt->jo_err_partial);
Bram Moolenaar4e221c92016-02-23 13:20:22 +01001190 if (opt->jo_set & JO_CLOSE_CALLBACK)
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02001191 set_callback(&channel->ch_close_cb, &channel->ch_close_partial,
1192 opt->jo_close_cb, opt->jo_close_partial);
Bram Moolenaar958dc692016-12-01 15:34:12 +01001193 channel->ch_drop_never = opt->jo_drop_never;
Bram Moolenaar187db502016-02-27 14:44:26 +01001194
1195 if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
1196 {
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001197 buf_T *buf;
1198
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +01001199 /* writing output to a buffer. Default mode is NL. */
1200 if (!(opt->jo_set & JO_OUT_MODE))
1201 channel->ch_part[PART_OUT].ch_mode = MODE_NL;
Bram Moolenaar29fd0382016-03-09 23:14:07 +01001202 if (opt->jo_set & JO_OUT_BUF)
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001203 {
1204 buf = buflist_findnr(opt->jo_io_buf[PART_OUT]);
1205 if (buf == NULL)
1206 EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_OUT]);
1207 }
Bram Moolenaar29fd0382016-03-09 23:14:07 +01001208 else
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001209 {
Bram Moolenaar169ebb02016-09-07 23:32:23 +02001210 int msg = TRUE;
1211
1212 if (opt->jo_set2 & JO2_OUT_MSG)
1213 msg = opt->jo_message[PART_OUT];
1214 buf = find_buffer(opt->jo_io_name[PART_OUT], FALSE, msg);
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001215 }
1216 if (buf != NULL)
1217 {
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02001218 if (opt->jo_set & JO_OUT_MODIFIABLE)
1219 channel->ch_part[PART_OUT].ch_nomodifiable =
1220 !opt->jo_modifiable[PART_OUT];
1221
1222 if (!buf->b_p_ma && !channel->ch_part[PART_OUT].ch_nomodifiable)
1223 {
1224 EMSG(_(e_modifiable));
1225 }
1226 else
1227 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001228 ch_log(channel, "writing out to buffer '%s'",
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001229 (char *)buf->b_ffname);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001230 set_bufref(&channel->ch_part[PART_OUT].ch_bufref, buf);
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02001231 }
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001232 }
Bram Moolenaar187db502016-02-27 14:44:26 +01001233 }
Bram Moolenaar6ff02c92016-03-08 20:12:44 +01001234
1235 if ((opt->jo_set & JO_ERR_IO) && (opt->jo_io[PART_ERR] == JIO_BUFFER
1236 || (opt->jo_io[PART_ERR] == JIO_OUT && (opt->jo_set & JO_OUT_IO)
1237 && opt->jo_io[PART_OUT] == JIO_BUFFER)))
1238 {
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001239 buf_T *buf;
1240
Bram Moolenaar6ff02c92016-03-08 20:12:44 +01001241 /* writing err to a buffer. Default mode is NL. */
1242 if (!(opt->jo_set & JO_ERR_MODE))
1243 channel->ch_part[PART_ERR].ch_mode = MODE_NL;
1244 if (opt->jo_io[PART_ERR] == JIO_OUT)
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001245 buf = channel->ch_part[PART_OUT].ch_bufref.br_buf;
Bram Moolenaar29fd0382016-03-09 23:14:07 +01001246 else if (opt->jo_set & JO_ERR_BUF)
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001247 {
1248 buf = buflist_findnr(opt->jo_io_buf[PART_ERR]);
1249 if (buf == NULL)
1250 EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_ERR]);
1251 }
Bram Moolenaar6ff02c92016-03-08 20:12:44 +01001252 else
Bram Moolenaar169ebb02016-09-07 23:32:23 +02001253 {
1254 int msg = TRUE;
1255
1256 if (opt->jo_set2 & JO2_ERR_MSG)
1257 msg = opt->jo_message[PART_ERR];
1258 buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE, msg);
1259 }
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001260 if (buf != NULL)
1261 {
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02001262 if (opt->jo_set & JO_ERR_MODIFIABLE)
1263 channel->ch_part[PART_ERR].ch_nomodifiable =
1264 !opt->jo_modifiable[PART_ERR];
1265 if (!buf->b_p_ma && !channel->ch_part[PART_ERR].ch_nomodifiable)
1266 {
1267 EMSG(_(e_modifiable));
1268 }
1269 else
1270 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001271 ch_log(channel, "writing err to buffer '%s'",
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001272 (char *)buf->b_ffname);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001273 set_bufref(&channel->ch_part[PART_ERR].ch_bufref, buf);
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02001274 }
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001275 }
Bram Moolenaar6ff02c92016-03-08 20:12:44 +01001276 }
Bram Moolenaar03602ec2016-03-20 20:57:45 +01001277
1278 channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT];
1279 channel->ch_part[PART_ERR].ch_io = opt->jo_io[PART_ERR];
1280 channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN];
Bram Moolenaar910b8aa2016-02-16 21:03:07 +01001281}
1282
1283/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001284 * Set the callback for "channel"/"part" for the response with "id".
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001285 */
1286 void
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001287channel_set_req_callback(
Bram Moolenaar1735bc92016-03-14 23:05:14 +01001288 channel_T *channel,
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001289 ch_part_T part,
Bram Moolenaar1735bc92016-03-14 23:05:14 +01001290 char_u *callback,
1291 partial_T *partial,
1292 int id)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001293{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001294 cbq_T *head = &channel->ch_part[part].ch_cb_head;
Bram Moolenaara07fec92016-02-05 21:04:08 +01001295 cbq_T *item = (cbq_T *)alloc((int)sizeof(cbq_T));
1296
1297 if (item != NULL)
1298 {
Bram Moolenaar1735bc92016-03-14 23:05:14 +01001299 item->cq_partial = partial;
1300 if (partial != NULL)
Bram Moolenaar57e69ff2016-07-30 23:05:09 +02001301 {
Bram Moolenaar1735bc92016-03-14 23:05:14 +01001302 ++partial->pt_refcount;
Bram Moolenaar57e69ff2016-07-30 23:05:09 +02001303 item->cq_callback = callback;
1304 }
1305 else
Bram Moolenaar437bafe2016-08-01 15:40:54 +02001306 {
Bram Moolenaar57e69ff2016-07-30 23:05:09 +02001307 item->cq_callback = vim_strsave(callback);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02001308 func_ref(item->cq_callback);
1309 }
Bram Moolenaar77073442016-02-13 23:23:53 +01001310 item->cq_seq_nr = id;
1311 item->cq_prev = head->cq_prev;
1312 head->cq_prev = item;
1313 item->cq_next = NULL;
1314 if (item->cq_prev == NULL)
1315 head->cq_next = item;
1316 else
1317 item->cq_prev->cq_next = item;
Bram Moolenaara07fec92016-02-05 21:04:08 +01001318 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001319}
1320
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001321 static void
1322write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel)
1323{
1324 char_u *line = ml_get_buf(buf, lnum, FALSE);
Bram Moolenaar367aabd2016-03-08 17:13:06 +01001325 int len = (int)STRLEN(line);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001326 char_u *p;
Bram Moolenaarbf2cc5f2016-07-07 20:45:06 +02001327 int i;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001328
Bram Moolenaar655da312016-05-28 22:22:34 +02001329 /* Need to make a copy to be able to append a NL. */
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001330 if ((p = alloc(len + 2)) == NULL)
1331 return;
Bram Moolenaaradb78a72016-06-27 21:10:31 +02001332 memcpy((char *)p, (char *)line, len);
Bram Moolenaarbf2cc5f2016-07-07 20:45:06 +02001333
Bram Moolenaaref68e4f2017-09-02 16:28:36 +02001334 if (channel->ch_write_text_mode)
1335 p[len] = CAR;
1336 else
1337 {
1338 for (i = 0; i < len; ++i)
1339 if (p[i] == NL)
1340 p[i] = NUL;
Bram Moolenaarbf2cc5f2016-07-07 20:45:06 +02001341
Bram Moolenaaref68e4f2017-09-02 16:28:36 +02001342 p[len] = NL;
1343 }
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001344 p[len + 1] = NUL;
Bram Moolenaar79cbdcb2016-11-11 21:14:03 +01001345 channel_send(channel, PART_IN, p, len + 1, "write_buf_line");
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001346 vim_free(p);
1347}
1348
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001349/*
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001350 * Return TRUE if "channel" can be written to.
1351 * Returns FALSE if the input is closed or the write would block.
1352 */
1353 static int
1354can_write_buf_line(channel_T *channel)
1355{
1356 chanpart_T *in_part = &channel->ch_part[PART_IN];
1357
1358 if (in_part->ch_fd == INVALID_FD)
1359 return FALSE; /* pipe was closed */
1360
1361 /* for testing: block every other attempt to write */
1362 if (in_part->ch_block_write == 1)
1363 in_part->ch_block_write = -1;
1364 else if (in_part->ch_block_write == -1)
1365 in_part->ch_block_write = 1;
1366
1367 /* TODO: Win32 implementation, probably using WaitForMultipleObjects() */
1368#ifndef WIN32
1369 {
1370# if defined(HAVE_SELECT)
1371 struct timeval tval;
1372 fd_set wfds;
1373 int ret;
1374
1375 FD_ZERO(&wfds);
1376 FD_SET((int)in_part->ch_fd, &wfds);
1377 tval.tv_sec = 0;
1378 tval.tv_usec = 0;
1379 for (;;)
1380 {
1381 ret = select((int)in_part->ch_fd + 1, NULL, &wfds, NULL, &tval);
1382# ifdef EINTR
1383 SOCK_ERRNO;
1384 if (ret == -1 && errno == EINTR)
1385 continue;
1386# endif
1387 if (ret <= 0 || in_part->ch_block_write == 1)
1388 {
1389 if (ret > 0)
1390 ch_log(channel, "FAKED Input not ready for writing");
1391 else
1392 ch_log(channel, "Input not ready for writing");
1393 return FALSE;
1394 }
1395 break;
1396 }
1397# else
1398 struct pollfd fds;
1399
1400 fds.fd = in_part->ch_fd;
1401 fds.events = POLLOUT;
1402 if (poll(&fds, 1, 0) <= 0)
1403 {
1404 ch_log(channel, "Input not ready for writing");
1405 return FALSE;
1406 }
1407 if (in_part->ch_block_write == 1)
1408 {
1409 ch_log(channel, "FAKED Input not ready for writing");
1410 return FALSE;
1411 }
1412# endif
1413 }
1414#endif
1415 return TRUE;
1416}
1417
1418/*
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02001419 * Write any buffer lines to the input channel.
Bram Moolenaar014069a2016-03-03 22:51:40 +01001420 */
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001421 static void
Bram Moolenaar014069a2016-03-03 22:51:40 +01001422channel_write_in(channel_T *channel)
1423{
1424 chanpart_T *in_part = &channel->ch_part[PART_IN];
1425 linenr_T lnum;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001426 buf_T *buf = in_part->ch_bufref.br_buf;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001427 int written = 0;
Bram Moolenaar014069a2016-03-03 22:51:40 +01001428
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001429 if (buf == NULL || in_part->ch_buf_append)
1430 return; /* no buffer or using appending */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001431 if (!bufref_valid(&in_part->ch_bufref) || buf->b_ml.ml_mfp == NULL)
Bram Moolenaar014069a2016-03-03 22:51:40 +01001432 {
1433 /* buffer was wiped out or unloaded */
Bram Moolenaarc4da1132017-07-15 19:39:43 +02001434 ch_log(channel, "input buffer has been wiped out");
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001435 in_part->ch_bufref.br_buf = NULL;
Bram Moolenaar014069a2016-03-03 22:51:40 +01001436 return;
1437 }
Bram Moolenaar014069a2016-03-03 22:51:40 +01001438
1439 for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot
1440 && lnum <= buf->b_ml.ml_line_count; ++lnum)
1441 {
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001442 if (!can_write_buf_line(channel))
1443 break;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001444 write_buf_line(buf, lnum, channel);
1445 ++written;
Bram Moolenaar014069a2016-03-03 22:51:40 +01001446 }
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001447
1448 if (written == 1)
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001449 ch_log(channel, "written line %d to channel", (int)lnum - 1);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001450 else if (written > 1)
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001451 ch_log(channel, "written %d lines to channel", written);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001452
Bram Moolenaar014069a2016-03-03 22:51:40 +01001453 in_part->ch_buf_top = lnum;
Bram Moolenaard8b55492016-09-01 14:35:22 +02001454 if (lnum > buf->b_ml.ml_line_count || lnum > in_part->ch_buf_bot)
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001455 {
Bram Moolenaardada6d22017-09-02 17:18:35 +02001456#if defined(FEAT_TERMINAL)
1457 /* Send CTRL-D or "eof_chars" to close stdin on MS-Windows. */
Bram Moolenaar3346cc42017-09-02 14:54:21 +02001458 if (channel->ch_job != NULL)
1459 term_send_eof(channel);
1460#endif
1461
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001462 /* Writing is done, no longer need the buffer. */
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001463 in_part->ch_bufref.br_buf = NULL;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001464 ch_log(channel, "Finished writing all lines to channel");
Bram Moolenaard8b55492016-09-01 14:35:22 +02001465
1466 /* Close the pipe/socket, so that the other side gets EOF. */
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001467 ch_close_part(channel, PART_IN);
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001468 }
1469 else
Bram Moolenaar4ac2e8d2018-04-08 12:38:26 +02001470 ch_log(channel, "Still %ld more lines to write",
1471 (long)(buf->b_ml.ml_line_count - lnum + 1));
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001472}
1473
1474/*
Bram Moolenaaraad30bb2016-06-26 17:31:03 +02001475 * Handle buffer "buf" being freed, remove it from any channels.
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001476 */
1477 void
1478channel_buffer_free(buf_T *buf)
1479{
1480 channel_T *channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001481 ch_part_T part;
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001482
1483 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001484 for (part = PART_SOCK; part < PART_COUNT; ++part)
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001485 {
1486 chanpart_T *ch_part = &channel->ch_part[part];
1487
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001488 if (ch_part->ch_bufref.br_buf == buf)
Bram Moolenaarde7eb0a2016-05-09 20:54:33 +02001489 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001490 ch_log(channel, "%s buffer has been wiped out",
Bram Moolenaarde7eb0a2016-05-09 20:54:33 +02001491 part_names[part]);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001492 ch_part->ch_bufref.br_buf = NULL;
Bram Moolenaarde7eb0a2016-05-09 20:54:33 +02001493 }
Bram Moolenaare0f76d02016-05-09 20:38:53 +02001494 }
1495}
1496
1497/*
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02001498 * Write any lines waiting to be written to "channel".
1499 */
1500 static void
1501channel_write_input(channel_T *channel)
1502{
1503 chanpart_T *in_part = &channel->ch_part[PART_IN];
1504
1505 if (in_part->ch_writeque.wq_next != NULL)
1506 channel_send(channel, PART_IN, (char_u *)"", 0, "channel_write_input");
1507 else if (in_part->ch_bufref.br_buf != NULL)
1508 {
1509 if (in_part->ch_buf_append)
1510 channel_write_new_lines(in_part->ch_bufref.br_buf);
1511 else
1512 channel_write_in(channel);
1513 }
1514}
1515
1516/*
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001517 * Write any lines waiting to be written to a channel.
1518 */
1519 void
Bram Moolenaarcf089462016-06-12 21:18:43 +02001520channel_write_any_lines(void)
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001521{
1522 channel_T *channel;
1523
1524 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02001525 channel_write_input(channel);
Bram Moolenaar014069a2016-03-03 22:51:40 +01001526}
1527
1528/*
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001529 * Write appended lines above the last one in "buf" to the channel.
1530 */
1531 void
1532channel_write_new_lines(buf_T *buf)
1533{
1534 channel_T *channel;
1535 int found_one = FALSE;
1536
1537 /* There could be more than one channel for the buffer, loop over all of
1538 * them. */
1539 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
1540 {
1541 chanpart_T *in_part = &channel->ch_part[PART_IN];
1542 linenr_T lnum;
1543 int written = 0;
1544
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001545 if (in_part->ch_bufref.br_buf == buf && in_part->ch_buf_append)
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001546 {
1547 if (in_part->ch_fd == INVALID_FD)
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001548 continue; /* pipe was closed */
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001549 found_one = TRUE;
1550 for (lnum = in_part->ch_buf_bot; lnum < buf->b_ml.ml_line_count;
1551 ++lnum)
1552 {
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001553 if (!can_write_buf_line(channel))
1554 break;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001555 write_buf_line(buf, lnum, channel);
1556 ++written;
1557 }
1558
1559 if (written == 1)
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001560 ch_log(channel, "written line %d to channel", (int)lnum - 1);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001561 else if (written > 1)
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001562 ch_log(channel, "written %d lines to channel", written);
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02001563 if (lnum < buf->b_ml.ml_line_count)
Bram Moolenaar4ac2e8d2018-04-08 12:38:26 +02001564 ch_log(channel, "Still %ld more lines to write",
1565 (long)(buf->b_ml.ml_line_count - lnum));
Bram Moolenaar99ef0622016-03-06 20:22:25 +01001566
1567 in_part->ch_buf_bot = lnum;
1568 }
1569 }
1570 if (!found_one)
1571 buf->b_write_to_channel = FALSE;
1572}
1573
1574/*
Bram Moolenaar77073442016-02-13 23:23:53 +01001575 * Invoke the "callback" on channel "channel".
Bram Moolenaar7f7c3322016-04-18 19:27:24 +02001576 * This does not redraw but sets channel_need_redraw;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001577 */
1578 static void
Bram Moolenaar1735bc92016-03-14 23:05:14 +01001579invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
1580 typval_T *argv)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001581{
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001582 typval_T rettv;
1583 int dummy;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001584
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +02001585 if (safe_to_invoke_callback == 0)
Bram Moolenaarde330112017-01-08 20:50:52 +01001586 IEMSG("INTERNAL: Invoking callback when it is not safe");
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +02001587
Bram Moolenaar77073442016-02-13 23:23:53 +01001588 argv[0].v_type = VAR_CHANNEL;
1589 argv[0].vval.v_channel = channel;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001590
Bram Moolenaardf48fb42016-07-22 21:50:18 +02001591 call_func(callback, (int)STRLEN(callback), &rettv, 2, argv, NULL,
1592 0L, 0L, &dummy, TRUE, partial, NULL);
Bram Moolenaaree1cffc2016-02-21 19:14:41 +01001593 clear_tv(&rettv);
Bram Moolenaar7f7c3322016-04-18 19:27:24 +02001594 channel_need_redraw = TRUE;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001595}
1596
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01001597/*
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001598 * Return the first node from "channel"/"part" without removing it.
1599 * Returns NULL if there is nothing.
1600 */
1601 readq_T *
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001602channel_peek(channel_T *channel, ch_part_T part)
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001603{
1604 readq_T *head = &channel->ch_part[part].ch_head;
1605
1606 return head->rq_next;
1607}
1608
1609/*
1610 * Return a pointer to the first NL in "node".
1611 * Skips over NUL characters.
1612 * Returns NULL if there is no NL.
1613 */
1614 char_u *
1615channel_first_nl(readq_T *node)
1616{
1617 char_u *buffer = node->rq_buffer;
1618 long_u i;
1619
1620 for (i = 0; i < node->rq_buflen; ++i)
1621 if (buffer[i] == NL)
1622 return buffer + i;
1623 return NULL;
1624}
1625
1626/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001627 * Return the first buffer from channel "channel"/"part" and remove it.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001628 * The caller must free it.
1629 * Returns NULL if there is nothing.
1630 */
1631 char_u *
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001632channel_get(channel_T *channel, ch_part_T part)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001633{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001634 readq_T *head = &channel->ch_part[part].ch_head;
Bram Moolenaar77073442016-02-13 23:23:53 +01001635 readq_T *node = head->rq_next;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001636 char_u *p;
1637
Bram Moolenaar77073442016-02-13 23:23:53 +01001638 if (node == NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001639 return NULL;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001640 /* dispose of the node but keep the buffer */
Bram Moolenaar77073442016-02-13 23:23:53 +01001641 p = node->rq_buffer;
1642 head->rq_next = node->rq_next;
1643 if (node->rq_next == NULL)
1644 head->rq_prev = NULL;
1645 else
1646 node->rq_next->rq_prev = NULL;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001647 vim_free(node);
1648 return p;
1649}
1650
1651/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001652 * Returns the whole buffer contents concatenated for "channel"/"part".
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001653 * Replaces NUL bytes with NL.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001654 */
1655 static char_u *
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001656channel_get_all(channel_T *channel, ch_part_T part)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001657{
Bram Moolenaaree1f7b32016-03-28 14:42:14 +02001658 readq_T *head = &channel->ch_part[part].ch_head;
1659 readq_T *node = head->rq_next;
Bram Moolenaaradb78a72016-06-27 21:10:31 +02001660 long_u len = 0;
Bram Moolenaaree1f7b32016-03-28 14:42:14 +02001661 char_u *res;
1662 char_u *p;
1663
1664 /* If there is only one buffer just get that one. */
1665 if (head->rq_next == NULL || head->rq_next->rq_next == NULL)
1666 return channel_get(channel, part);
1667
1668 /* Concatenate everything into one buffer. */
1669 for (node = head->rq_next; node != NULL; node = node->rq_next)
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001670 len += node->rq_buflen;
Bram Moolenaaradb78a72016-06-27 21:10:31 +02001671 res = lalloc(len + 1, TRUE);
Bram Moolenaaree1f7b32016-03-28 14:42:14 +02001672 if (res == NULL)
1673 return NULL;
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001674 p = res;
Bram Moolenaaree1f7b32016-03-28 14:42:14 +02001675 for (node = head->rq_next; node != NULL; node = node->rq_next)
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001676 {
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001677 mch_memmove(p, node->rq_buffer, node->rq_buflen);
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001678 p += node->rq_buflen;
1679 }
1680 *p = NUL;
Bram Moolenaaree1f7b32016-03-28 14:42:14 +02001681
1682 /* Free all buffers */
1683 do
1684 {
1685 p = channel_get(channel, part);
1686 vim_free(p);
1687 } while (p != NULL);
1688
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001689 /* turn all NUL into NL */
1690 while (len > 0)
1691 {
1692 --len;
1693 if (res[len] == NUL)
1694 res[len] = NL;
1695 }
1696
Bram Moolenaaree1f7b32016-03-28 14:42:14 +02001697 return res;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001698}
1699
1700/*
Bram Moolenaarcf089462016-06-12 21:18:43 +02001701 * Consume "len" bytes from the head of "node".
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001702 * Caller must check these bytes are available.
1703 */
1704 void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001705channel_consume(channel_T *channel, ch_part_T part, int len)
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001706{
1707 readq_T *head = &channel->ch_part[part].ch_head;
1708 readq_T *node = head->rq_next;
1709 char_u *buf = node->rq_buffer;
1710
1711 mch_memmove(buf, buf + len, node->rq_buflen - len);
1712 node->rq_buflen -= len;
1713}
1714
1715/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001716 * Collapses the first and second buffer for "channel"/"part".
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001717 * Returns FAIL if that is not possible.
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001718 * When "want_nl" is TRUE collapse more buffers until a NL is found.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001719 */
1720 int
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001721channel_collapse(channel_T *channel, ch_part_T part, int want_nl)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001722{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001723 readq_T *head = &channel->ch_part[part].ch_head;
Bram Moolenaar77073442016-02-13 23:23:53 +01001724 readq_T *node = head->rq_next;
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001725 readq_T *last_node;
1726 readq_T *n;
1727 char_u *newbuf;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001728 char_u *p;
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001729 long_u len;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001730
Bram Moolenaar77073442016-02-13 23:23:53 +01001731 if (node == NULL || node->rq_next == NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001732 return FAIL;
1733
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001734 last_node = node->rq_next;
1735 len = node->rq_buflen + last_node->rq_buflen + 1;
1736 if (want_nl)
1737 while (last_node->rq_next != NULL
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001738 && channel_first_nl(last_node) == NULL)
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001739 {
1740 last_node = last_node->rq_next;
1741 len += last_node->rq_buflen;
1742 }
1743
1744 p = newbuf = alloc(len);
1745 if (newbuf == NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001746 return FAIL; /* out of memory */
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001747 mch_memmove(p, node->rq_buffer, node->rq_buflen);
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001748 p += node->rq_buflen;
Bram Moolenaar77073442016-02-13 23:23:53 +01001749 vim_free(node->rq_buffer);
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001750 node->rq_buffer = newbuf;
1751 for (n = node; n != last_node; )
1752 {
1753 n = n->rq_next;
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001754 mch_memmove(p, n->rq_buffer, n->rq_buflen);
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001755 p += n->rq_buflen;
1756 vim_free(n->rq_buffer);
1757 }
Bram Moolenaarbbe8d912016-06-05 16:10:57 +02001758 node->rq_buflen = (long_u)(p - newbuf);
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001759
1760 /* dispose of the collapsed nodes and their buffers */
1761 for (n = node->rq_next; n != last_node; )
1762 {
1763 n = n->rq_next;
1764 vim_free(n->rq_prev);
1765 }
1766 node->rq_next = last_node->rq_next;
1767 if (last_node->rq_next == NULL)
1768 head->rq_prev = node;
1769 else
1770 last_node->rq_next->rq_prev = node;
1771 vim_free(last_node);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001772 return OK;
1773}
1774
1775/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001776 * Store "buf[len]" on "channel"/"part".
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001777 * When "prepend" is TRUE put in front, otherwise append at the end.
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001778 * Returns OK or FAIL.
1779 */
1780 static int
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001781channel_save(channel_T *channel, ch_part_T part, char_u *buf, int len,
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001782 int prepend, char *lead)
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001783{
1784 readq_T *node;
1785 readq_T *head = &channel->ch_part[part].ch_head;
1786 char_u *p;
1787 int i;
1788
1789 node = (readq_T *)alloc(sizeof(readq_T));
1790 if (node == NULL)
1791 return FAIL; /* out of memory */
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02001792 /* A NUL is added at the end, because netbeans code expects that.
1793 * Otherwise a NUL may appear inside the text. */
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001794 node->rq_buffer = alloc(len + 1);
1795 if (node->rq_buffer == NULL)
1796 {
1797 vim_free(node);
1798 return FAIL; /* out of memory */
1799 }
1800
1801 if (channel->ch_part[part].ch_mode == MODE_NL)
1802 {
1803 /* Drop any CR before a NL. */
1804 p = node->rq_buffer;
1805 for (i = 0; i < len; ++i)
1806 if (buf[i] != CAR || i + 1 >= len || buf[i + 1] != NL)
1807 *p++ = buf[i];
1808 *p = NUL;
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001809 node->rq_buflen = (long_u)(p - node->rq_buffer);
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001810 }
1811 else
1812 {
1813 mch_memmove(node->rq_buffer, buf, len);
1814 node->rq_buffer[len] = NUL;
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02001815 node->rq_buflen = (long_u)len;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001816 }
1817
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001818 if (prepend)
1819 {
1820 /* preend node to the head of the queue */
1821 node->rq_next = head->rq_next;
1822 node->rq_prev = NULL;
1823 if (head->rq_next == NULL)
1824 head->rq_prev = node;
1825 else
1826 head->rq_next->rq_prev = node;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001827 head->rq_next = node;
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001828 }
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001829 else
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001830 {
1831 /* append node to the tail of the queue */
1832 node->rq_next = NULL;
1833 node->rq_prev = head->rq_prev;
1834 if (head->rq_prev == NULL)
1835 head->rq_next = node;
1836 else
1837 head->rq_prev->rq_next = node;
1838 head->rq_prev = node;
1839 }
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001840
Bram Moolenaar71eeb742017-09-13 22:18:01 +02001841 if (ch_log_active() && lead != NULL)
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001842 {
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001843 ch_log_lead(lead, channel);
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001844 fprintf(log_fd, "'");
Bram Moolenaar71eeb742017-09-13 22:18:01 +02001845 ignored = (int)fwrite(buf, len, 1, log_fd);
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001846 fprintf(log_fd, "'\n");
1847 }
1848 return OK;
1849}
1850
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001851/*
1852 * Try to fill the buffer of "reader".
1853 * Returns FALSE when nothing was added.
1854 */
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001855 static int
1856channel_fill(js_read_T *reader)
1857{
1858 channel_T *channel = (channel_T *)reader->js_cookie;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001859 ch_part_T part = reader->js_cookie_arg;
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001860 char_u *next = channel_get(channel, part);
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001861 int keeplen;
1862 int addlen;
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001863 char_u *p;
1864
1865 if (next == NULL)
1866 return FALSE;
1867
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001868 keeplen = reader->js_end - reader->js_buf;
1869 if (keeplen > 0)
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001870 {
1871 /* Prepend unused text. */
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001872 addlen = (int)STRLEN(next);
1873 p = alloc(keeplen + addlen + 1);
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001874 if (p == NULL)
1875 {
1876 vim_free(next);
1877 return FALSE;
1878 }
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001879 mch_memmove(p, reader->js_buf, keeplen);
1880 mch_memmove(p + keeplen, next, addlen + 1);
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001881 vim_free(next);
1882 next = p;
1883 }
1884
1885 vim_free(reader->js_buf);
1886 reader->js_buf = next;
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001887 return TRUE;
1888}
1889
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001890/*
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001891 * Use the read buffer of "channel"/"part" and parse a JSON message that is
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001892 * complete. The messages are added to the queue.
Bram Moolenaard7ece102016-02-02 23:23:02 +01001893 * Return TRUE if there is more to read.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001894 */
Bram Moolenaard7ece102016-02-02 23:23:02 +01001895 static int
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02001896channel_parse_json(channel_T *channel, ch_part_T part)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001897{
1898 js_read_T reader;
1899 typval_T listtv;
1900 jsonq_T *item;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001901 chanpart_T *chanpart = &channel->ch_part[part];
1902 jsonq_T *head = &chanpart->ch_json_head;
1903 int status;
Bram Moolenaard7ece102016-02-02 23:23:02 +01001904 int ret;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001905
Bram Moolenaar42d38a22016-02-20 18:18:59 +01001906 if (channel_peek(channel, part) == NULL)
Bram Moolenaard7ece102016-02-02 23:23:02 +01001907 return FALSE;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001908
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001909 reader.js_buf = channel_get(channel, part);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001910 reader.js_used = 0;
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001911 reader.js_fill = channel_fill;
Bram Moolenaar77073442016-02-13 23:23:53 +01001912 reader.js_cookie = channel;
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001913 reader.js_cookie_arg = part;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001914
1915 /* When a message is incomplete we wait for a short while for more to
1916 * arrive. After the delay drop the input, otherwise a truncated string
Bram Moolenaar03c60c12017-01-10 15:15:37 +01001917 * or list will make us hang.
1918 * Do not generate error messages, they will be written in a channel log. */
1919 ++emsg_silent;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001920 status = json_decode(&reader, &listtv,
Bram Moolenaar46c00a62016-03-28 14:11:42 +02001921 chanpart->ch_mode == MODE_JS ? JSON_JS : 0);
Bram Moolenaar03c60c12017-01-10 15:15:37 +01001922 --emsg_silent;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001923 if (status == OK)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001924 {
Bram Moolenaar6076fe12016-02-05 22:49:56 +01001925 /* Only accept the response when it is a list with at least two
1926 * items. */
1927 if (listtv.v_type != VAR_LIST || listtv.vval.v_list->lv_len < 2)
Bram Moolenaard7ece102016-02-02 23:23:02 +01001928 {
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001929 if (listtv.v_type != VAR_LIST)
1930 ch_error(channel, "Did not receive a list, discarding");
1931 else
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001932 ch_error(channel, "Expected list with two items, got %d",
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001933 listtv.vval.v_list->lv_len);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001934 clear_tv(&listtv);
Bram Moolenaard7ece102016-02-02 23:23:02 +01001935 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001936 else
1937 {
Bram Moolenaard7ece102016-02-02 23:23:02 +01001938 item = (jsonq_T *)alloc((unsigned)sizeof(jsonq_T));
1939 if (item == NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001940 clear_tv(&listtv);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001941 else
1942 {
Bram Moolenaar958dc692016-12-01 15:34:12 +01001943 item->jq_no_callback = FALSE;
Bram Moolenaar77073442016-02-13 23:23:53 +01001944 item->jq_value = alloc_tv();
1945 if (item->jq_value == NULL)
Bram Moolenaard7ece102016-02-02 23:23:02 +01001946 {
1947 vim_free(item);
1948 clear_tv(&listtv);
1949 }
1950 else
1951 {
Bram Moolenaar77073442016-02-13 23:23:53 +01001952 *item->jq_value = listtv;
1953 item->jq_prev = head->jq_prev;
1954 head->jq_prev = item;
1955 item->jq_next = NULL;
1956 if (item->jq_prev == NULL)
1957 head->jq_next = item;
1958 else
1959 item->jq_prev->jq_next = item;
Bram Moolenaard7ece102016-02-02 23:23:02 +01001960 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001961 }
1962 }
1963 }
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01001964
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001965 if (status == OK)
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001966 chanpart->ch_wait_len = 0;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001967 else if (status == MAYBE)
Bram Moolenaard7ece102016-02-02 23:23:02 +01001968 {
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001969 size_t buflen = STRLEN(reader.js_buf);
1970
1971 if (chanpart->ch_wait_len < buflen)
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01001972 {
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001973 /* First time encountering incomplete message or after receiving
1974 * more (but still incomplete): set a deadline of 100 msec. */
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02001975 ch_log(channel,
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001976 "Incomplete message (%d bytes) - wait 100 msec for more",
Bram Moolenaarb113c3a2017-02-28 21:26:17 +01001977 (int)buflen);
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001978 reader.js_used = 0;
Bram Moolenaar88989cc2017-02-06 21:56:09 +01001979 chanpart->ch_wait_len = buflen;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001980#ifdef WIN32
1981 chanpart->ch_deadline = GetTickCount() + 100L;
1982#else
1983 gettimeofday(&chanpart->ch_deadline, NULL);
1984 chanpart->ch_deadline.tv_usec += 100 * 1000;
1985 if (chanpart->ch_deadline.tv_usec > 1000 * 1000)
1986 {
1987 chanpart->ch_deadline.tv_usec -= 1000 * 1000;
1988 ++chanpart->ch_deadline.tv_sec;
1989 }
1990#endif
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01001991 }
1992 else
1993 {
Bram Moolenaarba61ac02016-03-20 16:40:37 +01001994 int timeout;
1995#ifdef WIN32
1996 timeout = GetTickCount() > chanpart->ch_deadline;
1997#else
1998 {
1999 struct timeval now_tv;
2000
2001 gettimeofday(&now_tv, NULL);
2002 timeout = now_tv.tv_sec > chanpart->ch_deadline.tv_sec
2003 || (now_tv.tv_sec == chanpart->ch_deadline.tv_sec
2004 && now_tv.tv_usec > chanpart->ch_deadline.tv_usec);
2005 }
2006#endif
2007 if (timeout)
2008 {
2009 status = FAIL;
Bram Moolenaar88989cc2017-02-06 21:56:09 +01002010 chanpart->ch_wait_len = 0;
2011 ch_log(channel, "timed out");
Bram Moolenaarba61ac02016-03-20 16:40:37 +01002012 }
2013 else
2014 {
2015 reader.js_used = 0;
2016 ch_log(channel, "still waiting on incomplete message");
2017 }
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01002018 }
Bram Moolenaard7ece102016-02-02 23:23:02 +01002019 }
Bram Moolenaarba61ac02016-03-20 16:40:37 +01002020
2021 if (status == FAIL)
2022 {
2023 ch_error(channel, "Decoding failed - discarding input");
2024 ret = FALSE;
Bram Moolenaar88989cc2017-02-06 21:56:09 +01002025 chanpart->ch_wait_len = 0;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01002026 }
2027 else if (reader.js_buf[reader.js_used] != NUL)
2028 {
Bram Moolenaar46c00a62016-03-28 14:11:42 +02002029 /* Put the unread part back into the channel. */
Bram Moolenaarba61ac02016-03-20 16:40:37 +01002030 channel_save(channel, part, reader.js_buf + reader.js_used,
Bram Moolenaar46c00a62016-03-28 14:11:42 +02002031 (int)(reader.js_end - reader.js_buf) - reader.js_used,
2032 TRUE, NULL);
Bram Moolenaarba61ac02016-03-20 16:40:37 +01002033 ret = status == MAYBE ? FALSE: TRUE;
2034 }
Bram Moolenaard7ece102016-02-02 23:23:02 +01002035 else
2036 ret = FALSE;
2037
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01002038 vim_free(reader.js_buf);
Bram Moolenaard7ece102016-02-02 23:23:02 +01002039 return ret;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002040}
2041
2042/*
Bram Moolenaard46ae142016-02-16 13:33:52 +01002043 * Remove "node" from the queue that it is in. Does not free it.
Bram Moolenaara07fec92016-02-05 21:04:08 +01002044 */
2045 static void
Bram Moolenaar77073442016-02-13 23:23:53 +01002046remove_cb_node(cbq_T *head, cbq_T *node)
Bram Moolenaara07fec92016-02-05 21:04:08 +01002047{
Bram Moolenaar77073442016-02-13 23:23:53 +01002048 if (node->cq_prev == NULL)
2049 head->cq_next = node->cq_next;
2050 else
2051 node->cq_prev->cq_next = node->cq_next;
2052 if (node->cq_next == NULL)
2053 head->cq_prev = node->cq_prev;
2054 else
2055 node->cq_next->cq_prev = node->cq_prev;
Bram Moolenaara07fec92016-02-05 21:04:08 +01002056}
2057
2058/*
2059 * Remove "node" from the queue that it is in and free it.
Bram Moolenaar77073442016-02-13 23:23:53 +01002060 * Caller should have freed or used node->jq_value.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002061 */
2062 static void
Bram Moolenaar77073442016-02-13 23:23:53 +01002063remove_json_node(jsonq_T *head, jsonq_T *node)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002064{
Bram Moolenaar77073442016-02-13 23:23:53 +01002065 if (node->jq_prev == NULL)
2066 head->jq_next = node->jq_next;
2067 else
2068 node->jq_prev->jq_next = node->jq_next;
2069 if (node->jq_next == NULL)
2070 head->jq_prev = node->jq_prev;
2071 else
2072 node->jq_next->jq_prev = node->jq_prev;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002073 vim_free(node);
2074}
2075
2076/*
Bram Moolenaar77073442016-02-13 23:23:53 +01002077 * Get a message from the JSON queue for channel "channel".
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002078 * When "id" is positive it must match the first number in the list.
Bram Moolenaare56bf152016-02-08 23:23:42 +01002079 * When "id" is zero or negative jut get the first message. But not the one
2080 * with id ch_block_id.
Bram Moolenaar958dc692016-12-01 15:34:12 +01002081 * When "without_callback" is TRUE also get messages that were pushed back.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002082 * Return OK when found and return the value in "rettv".
2083 * Return FAIL otherwise.
2084 */
2085 static int
Bram Moolenaar958dc692016-12-01 15:34:12 +01002086channel_get_json(
2087 channel_T *channel,
2088 ch_part_T part,
2089 int id,
2090 int without_callback,
2091 typval_T **rettv)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002092{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002093 jsonq_T *head = &channel->ch_part[part].ch_json_head;
Bram Moolenaar77073442016-02-13 23:23:53 +01002094 jsonq_T *item = head->jq_next;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002095
Bram Moolenaar77073442016-02-13 23:23:53 +01002096 while (item != NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002097 {
Bram Moolenaar77073442016-02-13 23:23:53 +01002098 list_T *l = item->jq_value->vval.v_list;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002099 typval_T *tv = &l->lv_first->li_tv;
2100
Bram Moolenaar958dc692016-12-01 15:34:12 +01002101 if ((without_callback || !item->jq_no_callback)
2102 && ((id > 0 && tv->v_type == VAR_NUMBER && tv->vval.v_number == id)
Bram Moolenaare56bf152016-02-08 23:23:42 +01002103 || (id <= 0 && (tv->v_type != VAR_NUMBER
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002104 || tv->vval.v_number == 0
Bram Moolenaar958dc692016-12-01 15:34:12 +01002105 || tv->vval.v_number != channel->ch_part[part].ch_block_id))))
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002106 {
Bram Moolenaar77073442016-02-13 23:23:53 +01002107 *rettv = item->jq_value;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01002108 if (tv->v_type == VAR_NUMBER)
Bram Moolenaar4ac2e8d2018-04-08 12:38:26 +02002109 ch_log(channel, "Getting JSON message %ld",
2110 (long)tv->vval.v_number);
Bram Moolenaar77073442016-02-13 23:23:53 +01002111 remove_json_node(head, item);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002112 return OK;
2113 }
Bram Moolenaar77073442016-02-13 23:23:53 +01002114 item = item->jq_next;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002115 }
2116 return FAIL;
2117}
2118
Bram Moolenaar958dc692016-12-01 15:34:12 +01002119/*
2120 * Put back "rettv" into the JSON queue, there was no callback for it.
2121 * Takes over the values in "rettv".
2122 */
2123 static void
2124channel_push_json(channel_T *channel, ch_part_T part, typval_T *rettv)
2125{
2126 jsonq_T *head = &channel->ch_part[part].ch_json_head;
2127 jsonq_T *item = head->jq_next;
2128 jsonq_T *newitem;
2129
2130 if (head->jq_prev != NULL && head->jq_prev->jq_no_callback)
2131 /* last item was pushed back, append to the end */
2132 item = NULL;
2133 else while (item != NULL && item->jq_no_callback)
2134 /* append after the last item that was pushed back */
2135 item = item->jq_next;
2136
2137 newitem = (jsonq_T *)alloc((unsigned)sizeof(jsonq_T));
2138 if (newitem == NULL)
2139 clear_tv(rettv);
2140 else
2141 {
2142 newitem->jq_value = alloc_tv();
2143 if (newitem->jq_value == NULL)
2144 {
2145 vim_free(newitem);
2146 clear_tv(rettv);
2147 }
2148 else
2149 {
2150 newitem->jq_no_callback = FALSE;
2151 *newitem->jq_value = *rettv;
2152 if (item == NULL)
2153 {
2154 /* append to the end */
2155 newitem->jq_prev = head->jq_prev;
2156 head->jq_prev = newitem;
2157 newitem->jq_next = NULL;
2158 if (newitem->jq_prev == NULL)
2159 head->jq_next = newitem;
2160 else
2161 newitem->jq_prev->jq_next = newitem;
2162 }
2163 else
2164 {
2165 /* append after "item" */
2166 newitem->jq_prev = item;
2167 newitem->jq_next = item->jq_next;
2168 item->jq_next = newitem;
2169 if (newitem->jq_next == NULL)
2170 head->jq_prev = newitem;
2171 else
2172 newitem->jq_next->jq_prev = newitem;
2173 }
2174 }
2175 }
2176}
2177
Bram Moolenaarece61b02016-02-20 21:39:05 +01002178#define CH_JSON_MAX_ARGS 4
2179
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002180/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002181 * Execute a command received over "channel"/"part"
Bram Moolenaarece61b02016-02-20 21:39:05 +01002182 * "argv[0]" is the command string.
2183 * "argv[1]" etc. have further arguments, type is VAR_UNKNOWN if missing.
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002184 */
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002185 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002186channel_exe_cmd(channel_T *channel, ch_part_T part, typval_T *argv)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002187{
Bram Moolenaarece61b02016-02-20 21:39:05 +01002188 char_u *cmd = argv[0].vval.v_string;
2189 char_u *arg;
2190 int options = channel->ch_part[part].ch_mode == MODE_JS ? JSON_JS : 0;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002191
Bram Moolenaarece61b02016-02-20 21:39:05 +01002192 if (argv[1].v_type != VAR_STRING)
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002193 {
Bram Moolenaarece61b02016-02-20 21:39:05 +01002194 ch_error(channel, "received command with non-string argument");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002195 if (p_verbose > 2)
Bram Moolenaar5b302912016-08-24 22:11:55 +02002196 EMSG(_("E903: received command with non-string argument"));
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002197 return;
2198 }
Bram Moolenaarece61b02016-02-20 21:39:05 +01002199 arg = argv[1].vval.v_string;
Bram Moolenaar14ad6112016-02-01 21:47:13 +01002200 if (arg == NULL)
2201 arg = (char_u *)"";
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002202
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002203 if (STRCMP(cmd, "ex") == 0)
2204 {
Bram Moolenaarc4dcd602016-03-26 22:56:46 +01002205 int save_called_emsg = called_emsg;
2206
2207 called_emsg = FALSE;
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002208 ch_log(channel, "Executing ex command '%s'", (char *)arg);
Bram Moolenaarc4dcd602016-03-26 22:56:46 +01002209 ++emsg_silent;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002210 do_cmdline_cmd(arg);
Bram Moolenaarc4dcd602016-03-26 22:56:46 +01002211 --emsg_silent;
2212 if (called_emsg)
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002213 ch_log(channel, "Ex command error: '%s'",
Bram Moolenaarc4dcd602016-03-26 22:56:46 +01002214 (char *)get_vim_var_str(VV_ERRMSG));
2215 called_emsg = save_called_emsg;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002216 }
2217 else if (STRCMP(cmd, "normal") == 0)
2218 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002219 exarg_T ea;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002220
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002221 ch_log(channel, "Executing normal command '%s'", (char *)arg);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002222 ea.arg = arg;
2223 ea.addr_count = 0;
2224 ea.forceit = TRUE; /* no mapping */
2225 ex_normal(&ea);
2226 }
2227 else if (STRCMP(cmd, "redraw") == 0)
2228 {
2229 exarg_T ea;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002230
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01002231 ch_log(channel, "redraw");
Bram Moolenaar14ad6112016-02-01 21:47:13 +01002232 ea.forceit = *arg != NUL;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002233 ex_redraw(&ea);
2234 showruler(FALSE);
2235 setcursor();
Bram Moolenaara338adc2018-01-31 20:51:47 +01002236 out_flush_cursor(TRUE, FALSE);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002237 }
Bram Moolenaarece61b02016-02-20 21:39:05 +01002238 else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "call") == 0)
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002239 {
Bram Moolenaarece61b02016-02-20 21:39:05 +01002240 int is_call = cmd[0] == 'c';
2241 int id_idx = is_call ? 3 : 2;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002242
Bram Moolenaarece61b02016-02-20 21:39:05 +01002243 if (argv[id_idx].v_type != VAR_UNKNOWN
2244 && argv[id_idx].v_type != VAR_NUMBER)
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002245 {
Bram Moolenaarece61b02016-02-20 21:39:05 +01002246 ch_error(channel, "last argument for expr/call must be a number");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002247 if (p_verbose > 2)
Bram Moolenaar5b302912016-08-24 22:11:55 +02002248 EMSG(_("E904: last argument for expr/call must be a number"));
Bram Moolenaarece61b02016-02-20 21:39:05 +01002249 }
2250 else if (is_call && argv[2].v_type != VAR_LIST)
2251 {
2252 ch_error(channel, "third argument for call must be a list");
2253 if (p_verbose > 2)
Bram Moolenaar5b302912016-08-24 22:11:55 +02002254 EMSG(_("E904: third argument for call must be a list"));
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002255 }
2256 else
2257 {
Bram Moolenaarc8fe3382016-09-04 20:44:42 +02002258 typval_T *tv = NULL;
Bram Moolenaarece61b02016-02-20 21:39:05 +01002259 typval_T res_tv;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002260 typval_T err_tv;
Bram Moolenaar55fab432016-02-07 16:53:13 +01002261 char_u *json = NULL;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002262
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +01002263 /* Don't pollute the display with errors. */
2264 ++emsg_skip;
Bram Moolenaarece61b02016-02-20 21:39:05 +01002265 if (!is_call)
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01002266 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002267 ch_log(channel, "Evaluating expression '%s'", (char *)arg);
Bram Moolenaarece61b02016-02-20 21:39:05 +01002268 tv = eval_expr(arg, NULL);
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01002269 }
Bram Moolenaarece61b02016-02-20 21:39:05 +01002270 else
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01002271 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002272 ch_log(channel, "Calling '%s'", (char *)arg);
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01002273 if (func_call(arg, &argv[2], NULL, NULL, &res_tv) == OK)
2274 tv = &res_tv;
Bram Moolenaarac74d5e2016-03-20 14:31:00 +01002275 }
Bram Moolenaarece61b02016-02-20 21:39:05 +01002276
2277 if (argv[id_idx].v_type == VAR_NUMBER)
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002278 {
Bram Moolenaarece61b02016-02-20 21:39:05 +01002279 int id = argv[id_idx].vval.v_number;
2280
Bram Moolenaar55fab432016-02-07 16:53:13 +01002281 if (tv != NULL)
Bram Moolenaarf1f07922016-08-26 17:58:53 +02002282 json = json_encode_nr_expr(id, tv, options | JSON_NL);
Bram Moolenaar55fab432016-02-07 16:53:13 +01002283 if (tv == NULL || (json != NULL && *json == NUL))
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002284 {
Bram Moolenaar55fab432016-02-07 16:53:13 +01002285 /* If evaluation failed or the result can't be encoded
2286 * then return the string "ERROR". */
Bram Moolenaar77073442016-02-13 23:23:53 +01002287 vim_free(json);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002288 err_tv.v_type = VAR_STRING;
2289 err_tv.vval.v_string = (char_u *)"ERROR";
Bram Moolenaarc8fe3382016-09-04 20:44:42 +02002290 json = json_encode_nr_expr(id, &err_tv, options | JSON_NL);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002291 }
Bram Moolenaar55fab432016-02-07 16:53:13 +01002292 if (json != NULL)
2293 {
Bram Moolenaarece61b02016-02-20 21:39:05 +01002294 channel_send(channel,
2295 part == PART_SOCK ? PART_SOCK : PART_IN,
Bram Moolenaarbf2cc5f2016-07-07 20:45:06 +02002296 json, (int)STRLEN(json), (char *)cmd);
Bram Moolenaar55fab432016-02-07 16:53:13 +01002297 vim_free(json);
2298 }
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002299 }
Bram Moolenaar55fab432016-02-07 16:53:13 +01002300 --emsg_skip;
Bram Moolenaarece61b02016-02-20 21:39:05 +01002301 if (tv == &res_tv)
2302 clear_tv(tv);
Bram Moolenaarc8fe3382016-09-04 20:44:42 +02002303 else
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +01002304 free_tv(tv);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01002305 }
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002306 }
2307 else if (p_verbose > 2)
Bram Moolenaarece61b02016-02-20 21:39:05 +01002308 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002309 ch_error(channel, "Received unknown command: %s", (char *)cmd);
Bram Moolenaar5b302912016-08-24 22:11:55 +02002310 EMSG2(_("E905: received unknown command: %s"), cmd);
Bram Moolenaarece61b02016-02-20 21:39:05 +01002311 }
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002312}
2313
Bram Moolenaar7f7c3322016-04-18 19:27:24 +02002314/*
2315 * Invoke the callback at "cbhead".
2316 * Does not redraw but sets channel_need_redraw.
2317 */
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002318 static void
2319invoke_one_time_callback(
2320 channel_T *channel,
2321 cbq_T *cbhead,
2322 cbq_T *item,
2323 typval_T *argv)
2324{
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002325 ch_log(channel, "Invoking one-time callback %s",
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002326 (char *)item->cq_callback);
2327 /* Remove the item from the list first, if the callback
2328 * invokes ch_close() the list will be cleared. */
2329 remove_cb_node(cbhead, item);
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002330 invoke_callback(channel, item->cq_callback, item->cq_partial, argv);
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02002331 free_callback(item->cq_callback, item->cq_partial);
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002332 vim_free(item);
2333}
2334
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002335 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002336append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002337{
Bram Moolenaar6b7355a2017-08-04 21:37:54 +02002338 bufref_T save_curbuf = {NULL, 0, 0};
2339 win_T *save_curwin = NULL;
2340 tabpage_T *save_curtab = NULL;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002341 linenr_T lnum = buffer->b_ml.ml_line_count;
2342 int save_write_to = buffer->b_write_to_channel;
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02002343 chanpart_T *ch_part = &channel->ch_part[part];
2344 int save_p_ma = buffer->b_p_ma;
Bram Moolenaarc4da1132017-07-15 19:39:43 +02002345 int empty = (buffer->b_ml.ml_flags & ML_EMPTY) ? 1 : 0;
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02002346
2347 if (!buffer->b_p_ma && !ch_part->ch_nomodifiable)
2348 {
2349 if (!ch_part->ch_nomod_error)
2350 {
2351 ch_error(channel, "Buffer is not modifiable, cannot append");
2352 ch_part->ch_nomod_error = TRUE;
2353 }
2354 return;
2355 }
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002356
2357 /* If the buffer is also used as input insert above the last
2358 * line. Don't write these lines. */
2359 if (save_write_to)
2360 {
2361 --lnum;
2362 buffer->b_write_to_channel = FALSE;
2363 }
2364
2365 /* Append to the buffer */
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002366 ch_log(channel, "appending line %d to buffer", (int)lnum + 1 - empty);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002367
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02002368 buffer->b_p_ma = TRUE;
Bram Moolenaar6b7355a2017-08-04 21:37:54 +02002369
2370 /* Save curbuf/curwin/curtab and make "buffer" the current buffer. */
2371 switch_to_win_for_buf(buffer, &save_curwin, &save_curtab, &save_curbuf);
2372
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002373 u_sync(TRUE);
2374 /* ignore undo failure, undo is not very useful here */
Bram Moolenaarc4da1132017-07-15 19:39:43 +02002375 ignored = u_save(lnum - empty, lnum + 1);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002376
Bram Moolenaar169ebb02016-09-07 23:32:23 +02002377 if (empty)
2378 {
2379 /* The buffer is empty, replace the first (dummy) line. */
2380 ml_replace(lnum, msg, TRUE);
2381 lnum = 0;
2382 }
2383 else
2384 ml_append(lnum, msg, 0, FALSE);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002385 appended_lines_mark(lnum, 1L);
Bram Moolenaar6b7355a2017-08-04 21:37:54 +02002386
2387 /* Restore curbuf/curwin/curtab */
2388 restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
2389
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02002390 if (ch_part->ch_nomodifiable)
2391 buffer->b_p_ma = FALSE;
2392 else
2393 buffer->b_p_ma = save_p_ma;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002394
2395 if (buffer->b_nwindows > 0)
2396 {
2397 win_T *wp;
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002398
2399 FOR_ALL_WINDOWS(wp)
2400 {
2401 if (wp->w_buffer == buffer
2402 && (save_write_to
2403 ? wp->w_cursor.lnum == lnum + 1
2404 : (wp->w_cursor.lnum == lnum
2405 && wp->w_cursor.col == 0)))
2406 {
2407 ++wp->w_cursor.lnum;
2408 save_curwin = curwin;
2409 curwin = wp;
2410 curbuf = curwin->w_buffer;
2411 scroll_cursor_bot(0, FALSE);
2412 curwin = save_curwin;
2413 curbuf = curwin->w_buffer;
2414 }
2415 }
Bram Moolenaar29ae3772017-04-30 19:39:39 +02002416 redraw_buf_and_status_later(buffer, VALID);
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002417 channel_need_redraw = TRUE;
2418 }
2419
2420 if (save_write_to)
2421 {
2422 channel_T *ch;
2423
2424 /* Find channels reading from this buffer and adjust their
2425 * next-to-read line number. */
2426 buffer->b_write_to_channel = TRUE;
2427 for (ch = first_channel; ch != NULL; ch = ch->ch_next)
2428 {
2429 chanpart_T *in_part = &ch->ch_part[PART_IN];
2430
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02002431 if (in_part->ch_bufref.br_buf == buffer)
Bram Moolenaar99ef0622016-03-06 20:22:25 +01002432 in_part->ch_buf_bot = buffer->b_ml.ml_line_count;
2433 }
2434 }
2435}
2436
Bram Moolenaar437905c2016-04-26 19:01:05 +02002437 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002438drop_messages(channel_T *channel, ch_part_T part)
Bram Moolenaar437905c2016-04-26 19:01:05 +02002439{
2440 char_u *msg;
2441
2442 while ((msg = channel_get(channel, part)) != NULL)
2443 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002444 ch_log(channel, "Dropping message '%s'", (char *)msg);
Bram Moolenaar437905c2016-04-26 19:01:05 +02002445 vim_free(msg);
2446 }
2447}
2448
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002449/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002450 * Invoke a callback for "channel"/"part" if needed.
Bram Moolenaar7f7c3322016-04-18 19:27:24 +02002451 * This does not redraw but sets channel_need_redraw when redraw is needed.
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002452 * Return TRUE when a message was handled, there might be another one.
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002453 */
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01002454 static int
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002455may_invoke_callback(channel_T *channel, ch_part_T part)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002456{
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002457 char_u *msg = NULL;
2458 typval_T *listtv = NULL;
Bram Moolenaarece61b02016-02-20 21:39:05 +01002459 typval_T argv[CH_JSON_MAX_ARGS];
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002460 int seq_nr = -1;
Bram Moolenaarec68a992016-10-03 21:37:41 +02002461 chanpart_T *ch_part = &channel->ch_part[part];
2462 ch_mode_T ch_mode = ch_part->ch_mode;
2463 cbq_T *cbhead = &ch_part->ch_cb_head;
Bram Moolenaar5983ad02016-03-05 20:54:36 +01002464 cbq_T *cbitem;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002465 char_u *callback = NULL;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002466 partial_T *partial = NULL;
Bram Moolenaar187db502016-02-27 14:44:26 +01002467 buf_T *buffer = NULL;
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002468 char_u *p;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002469
Bram Moolenaar4e221c92016-02-23 13:20:22 +01002470 if (channel->ch_nb_close_cb != NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002471 /* this channel is handled elsewhere (netbeans) */
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01002472 return FALSE;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002473
Bram Moolenaar5983ad02016-03-05 20:54:36 +01002474 /* Use a message-specific callback, part callback or channel callback */
2475 for (cbitem = cbhead->cq_next; cbitem != NULL; cbitem = cbitem->cq_next)
2476 if (cbitem->cq_seq_nr == 0)
2477 break;
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002478 if (cbitem != NULL)
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002479 {
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002480 callback = cbitem->cq_callback;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002481 partial = cbitem->cq_partial;
2482 }
Bram Moolenaarec68a992016-10-03 21:37:41 +02002483 else if (ch_part->ch_callback != NULL)
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002484 {
Bram Moolenaarec68a992016-10-03 21:37:41 +02002485 callback = ch_part->ch_callback;
2486 partial = ch_part->ch_partial;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002487 }
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002488 else
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002489 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002490 callback = channel->ch_callback;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002491 partial = channel->ch_partial;
2492 }
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01002493
Bram Moolenaarec68a992016-10-03 21:37:41 +02002494 buffer = ch_part->ch_bufref.br_buf;
Bram Moolenaarc4da1132017-07-15 19:39:43 +02002495 if (buffer != NULL && (!bufref_valid(&ch_part->ch_bufref)
2496 || buffer->b_ml.ml_mfp == NULL))
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01002497 {
Bram Moolenaarc4da1132017-07-15 19:39:43 +02002498 /* buffer was wiped out or unloaded */
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002499 ch_log(channel, "%s buffer has been wiped out", part_names[part]);
Bram Moolenaarec68a992016-10-03 21:37:41 +02002500 ch_part->ch_bufref.br_buf = NULL;
Bram Moolenaarc7f0ebc2016-02-27 21:10:09 +01002501 buffer = NULL;
2502 }
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002503
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002504 if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002505 {
Bram Moolenaarece61b02016-02-20 21:39:05 +01002506 listitem_T *item;
2507 int argc = 0;
2508
Bram Moolenaard7ece102016-02-02 23:23:02 +01002509 /* Get any json message in the queue. */
Bram Moolenaar958dc692016-12-01 15:34:12 +01002510 if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002511 {
Bram Moolenaard7ece102016-02-02 23:23:02 +01002512 /* Parse readahead, return when there is still no message. */
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002513 channel_parse_json(channel, part);
Bram Moolenaar958dc692016-12-01 15:34:12 +01002514 if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL)
Bram Moolenaard7ece102016-02-02 23:23:02 +01002515 return FALSE;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002516 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002517
Bram Moolenaarece61b02016-02-20 21:39:05 +01002518 for (item = listtv->vval.v_list->lv_first;
2519 item != NULL && argc < CH_JSON_MAX_ARGS;
2520 item = item->li_next)
2521 argv[argc++] = item->li_tv;
2522 while (argc < CH_JSON_MAX_ARGS)
2523 argv[argc++].v_type = VAR_UNKNOWN;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002524
Bram Moolenaarece61b02016-02-20 21:39:05 +01002525 if (argv[0].v_type == VAR_STRING)
2526 {
Bram Moolenaarece61b02016-02-20 21:39:05 +01002527 /* ["cmd", arg] or ["cmd", arg, arg] or ["cmd", arg, arg, arg] */
Bram Moolenaarece61b02016-02-20 21:39:05 +01002528 channel_exe_cmd(channel, part, argv);
Bram Moolenaar77073442016-02-13 23:23:53 +01002529 free_tv(listtv);
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01002530 return TRUE;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002531 }
2532
Bram Moolenaarece61b02016-02-20 21:39:05 +01002533 if (argv[0].v_type != VAR_NUMBER)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002534 {
Bram Moolenaar77073442016-02-13 23:23:53 +01002535 ch_error(channel,
Bram Moolenaar81661fb2016-02-18 22:23:34 +01002536 "Dropping message with invalid sequence number type");
Bram Moolenaar77073442016-02-13 23:23:53 +01002537 free_tv(listtv);
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01002538 return FALSE;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002539 }
Bram Moolenaarece61b02016-02-20 21:39:05 +01002540 seq_nr = argv[0].vval.v_number;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002541 }
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002542 else if (channel_peek(channel, part) == NULL)
Bram Moolenaard7ece102016-02-02 23:23:02 +01002543 {
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002544 /* nothing to read on RAW or NL channel */
Bram Moolenaard7ece102016-02-02 23:23:02 +01002545 return FALSE;
2546 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01002547 else
2548 {
Bram Moolenaar187db502016-02-27 14:44:26 +01002549 /* If there is no callback or buffer drop the message. */
2550 if (callback == NULL && buffer == NULL)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002551 {
Bram Moolenaar437905c2016-04-26 19:01:05 +02002552 /* If there is a close callback it may use ch_read() to get the
2553 * messages. */
Bram Moolenaar958dc692016-12-01 15:34:12 +01002554 if (channel->ch_close_cb == NULL && !channel->ch_drop_never)
Bram Moolenaar437905c2016-04-26 19:01:05 +02002555 drop_messages(channel, part);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002556 return FALSE;
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002557 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002558
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002559 if (ch_mode == MODE_NL)
2560 {
Bram Moolenaarec68a992016-10-03 21:37:41 +02002561 char_u *nl = NULL;
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002562 char_u *buf;
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002563 readq_T *node;
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002564
2565 /* See if we have a message ending in NL in the first buffer. If
2566 * not try to concatenate the first and the second buffer. */
2567 while (TRUE)
2568 {
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002569 node = channel_peek(channel, part);
2570 nl = channel_first_nl(node);
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002571 if (nl != NULL)
2572 break;
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +02002573 if (channel_collapse(channel, part, TRUE) == FAIL)
Bram Moolenaarec68a992016-10-03 21:37:41 +02002574 {
2575 if (ch_part->ch_fd == INVALID_FD && node->rq_buflen > 0)
2576 break;
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002577 return FALSE; /* incomplete message */
Bram Moolenaarec68a992016-10-03 21:37:41 +02002578 }
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002579 }
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002580 buf = node->rq_buffer;
2581
Bram Moolenaarec68a992016-10-03 21:37:41 +02002582 if (nl == NULL)
2583 {
2584 /* Flush remaining message that is missing a NL. */
Bram Moolenaar866c6882017-04-07 14:02:01 +02002585 char_u *new_buf;
2586
2587 new_buf = vim_realloc(buf, node->rq_buflen + 1);
2588 if (new_buf == NULL)
2589 /* This might fail over and over again, should the message
2590 * be dropped? */
Bram Moolenaarec68a992016-10-03 21:37:41 +02002591 return FALSE;
Bram Moolenaar866c6882017-04-07 14:02:01 +02002592 buf = new_buf;
Bram Moolenaarec68a992016-10-03 21:37:41 +02002593 node->rq_buffer = buf;
2594 nl = buf + node->rq_buflen++;
2595 *nl = NUL;
2596 }
2597
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002598 /* Convert NUL to NL, the internal representation. */
2599 for (p = buf; p < nl && p < buf + node->rq_buflen; ++p)
2600 if (*p == NUL)
2601 *p = NL;
2602
2603 if (nl + 1 == buf + node->rq_buflen)
Bram Moolenaar187db502016-02-27 14:44:26 +01002604 {
2605 /* get the whole buffer, drop the NL */
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002606 msg = channel_get(channel, part);
Bram Moolenaar187db502016-02-27 14:44:26 +01002607 *nl = NUL;
2608 }
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002609 else
2610 {
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002611 /* Copy the message into allocated memory (excluding the NL)
2612 * and remove it from the buffer (including the NL). */
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002613 msg = vim_strnsave(buf, (int)(nl - buf));
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002614 channel_consume(channel, part, (int)(nl - buf) + 1);
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002615 }
2616 }
2617 else
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002618 {
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002619 /* For a raw channel we don't know where the message ends, just
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002620 * get everything we have.
2621 * Convert NUL to NL, the internal representation. */
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002622 msg = channel_get_all(channel, part);
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02002623 }
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01002624
Bram Moolenaarbf73b912016-03-02 21:16:59 +01002625 if (msg == NULL)
2626 return FALSE; /* out of memory (and avoids Coverity warning) */
2627
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01002628 argv[1].v_type = VAR_STRING;
2629 argv[1].vval.v_string = msg;
2630 }
2631
Bram Moolenaara07fec92016-02-05 21:04:08 +01002632 if (seq_nr > 0)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01002633 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002634 int done = FALSE;
Bram Moolenaara07fec92016-02-05 21:04:08 +01002635
Bram Moolenaar958dc692016-12-01 15:34:12 +01002636 /* JSON or JS mode: invoke the one-time callback with the matching nr */
Bram Moolenaar5983ad02016-03-05 20:54:36 +01002637 for (cbitem = cbhead->cq_next; cbitem != NULL; cbitem = cbitem->cq_next)
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002638 if (cbitem->cq_seq_nr == seq_nr)
Bram Moolenaara07fec92016-02-05 21:04:08 +01002639 {
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002640 invoke_one_time_callback(channel, cbhead, cbitem, argv);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002641 done = TRUE;
Bram Moolenaara07fec92016-02-05 21:04:08 +01002642 break;
2643 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002644 if (!done)
Bram Moolenaar958dc692016-12-01 15:34:12 +01002645 {
2646 if (channel->ch_drop_never)
2647 {
2648 /* message must be read with ch_read() */
2649 channel_push_json(channel, part, listtv);
2650 listtv = NULL;
2651 }
2652 else
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002653 ch_log(channel, "Dropping message %d without callback",
Bram Moolenaar958dc692016-12-01 15:34:12 +01002654 seq_nr);
2655 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01002656 }
Bram Moolenaar187db502016-02-27 14:44:26 +01002657 else if (callback != NULL || buffer != NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002658 {
Bram Moolenaar187db502016-02-27 14:44:26 +01002659 if (buffer != NULL)
2660 {
Bram Moolenaarcc7f8be2016-02-29 22:55:56 +01002661 if (msg == NULL)
2662 /* JSON or JS mode: re-encode the message. */
2663 msg = json_encode(listtv, ch_mode);
2664 if (msg != NULL)
Bram Moolenaarcb8bbe92017-07-16 13:48:22 +02002665 {
Bram Moolenaarc0aa4822017-07-16 14:04:29 +02002666#ifdef FEAT_TERMINAL
Bram Moolenaarcb8bbe92017-07-16 13:48:22 +02002667 if (buffer->b_term != NULL)
2668 write_to_term(buffer, msg, channel);
2669 else
Bram Moolenaarc0aa4822017-07-16 14:04:29 +02002670#endif
Bram Moolenaarcb8bbe92017-07-16 13:48:22 +02002671 append_to_buffer(buffer, msg, channel, part);
2672 }
Bram Moolenaar187db502016-02-27 14:44:26 +01002673 }
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002674
Bram Moolenaar187db502016-02-27 14:44:26 +01002675 if (callback != NULL)
2676 {
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002677 if (cbitem != NULL)
2678 invoke_one_time_callback(channel, cbhead, cbitem, argv);
2679 else
2680 {
2681 /* invoke the channel callback */
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002682 ch_log(channel, "Invoking channel callback %s",
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002683 (char *)callback);
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002684 invoke_callback(channel, callback, partial, argv);
Bram Moolenaard6547fc2016-03-03 19:35:02 +01002685 }
Bram Moolenaar187db502016-02-27 14:44:26 +01002686 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002687 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002688 else
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002689 ch_log(channel, "Dropping message %d", seq_nr);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01002690
Bram Moolenaar19d2f152016-02-01 21:38:19 +01002691 if (listtv != NULL)
Bram Moolenaar77073442016-02-13 23:23:53 +01002692 free_tv(listtv);
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01002693 vim_free(msg);
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01002694
2695 return TRUE;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01002696}
2697
2698/*
Bram Moolenaar77073442016-02-13 23:23:53 +01002699 * Return TRUE when channel "channel" is open for writing to.
2700 * Also returns FALSE or invalid "channel".
Bram Moolenaard04a0202016-01-26 23:30:18 +01002701 */
2702 int
Bram Moolenaar77073442016-02-13 23:23:53 +01002703channel_can_write_to(channel_T *channel)
Bram Moolenaard04a0202016-01-26 23:30:18 +01002704{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002705 return channel != NULL && (channel->CH_SOCK_FD != INVALID_FD
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01002706 || channel->CH_IN_FD != INVALID_FD);
Bram Moolenaard04a0202016-01-26 23:30:18 +01002707}
2708
2709/*
Bram Moolenaar77073442016-02-13 23:23:53 +01002710 * Return TRUE when channel "channel" is open for reading or writing.
2711 * Also returns FALSE for invalid "channel".
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002712 */
2713 int
Bram Moolenaar77073442016-02-13 23:23:53 +01002714channel_is_open(channel_T *channel)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002715{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002716 return channel != NULL && (channel->CH_SOCK_FD != INVALID_FD
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002717 || channel->CH_IN_FD != INVALID_FD
2718 || channel->CH_OUT_FD != INVALID_FD
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01002719 || channel->CH_ERR_FD != INVALID_FD);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01002720}
2721
2722/*
Bram Moolenaar437905c2016-04-26 19:01:05 +02002723 * Return TRUE if "channel" has JSON or other typeahead.
2724 */
Bram Moolenaar4b785f62016-11-29 21:54:44 +01002725 int
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002726channel_has_readahead(channel_T *channel, ch_part_T part)
Bram Moolenaar437905c2016-04-26 19:01:05 +02002727{
2728 ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
2729
2730 if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
2731 {
2732 jsonq_T *head = &channel->ch_part[part].ch_json_head;
2733 jsonq_T *item = head->jq_next;
2734
2735 return item != NULL;
2736 }
2737 return channel_peek(channel, part) != NULL;
2738}
2739
2740/*
Bram Moolenaar77073442016-02-13 23:23:53 +01002741 * Return a string indicating the status of the channel.
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002742 * If "req_part" is not negative check that part.
Bram Moolenaar77073442016-02-13 23:23:53 +01002743 */
2744 char *
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002745channel_status(channel_T *channel, int req_part)
Bram Moolenaar77073442016-02-13 23:23:53 +01002746{
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002747 ch_part_T part;
Bram Moolenaar437905c2016-04-26 19:01:05 +02002748 int has_readahead = FALSE;
2749
Bram Moolenaar77073442016-02-13 23:23:53 +01002750 if (channel == NULL)
2751 return "fail";
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002752 if (req_part == PART_OUT)
2753 {
2754 if (channel->CH_OUT_FD != INVALID_FD)
2755 return "open";
2756 if (channel_has_readahead(channel, PART_OUT))
Bram Moolenaar437905c2016-04-26 19:01:05 +02002757 has_readahead = TRUE;
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002758 }
2759 else if (req_part == PART_ERR)
2760 {
2761 if (channel->CH_ERR_FD != INVALID_FD)
2762 return "open";
2763 if (channel_has_readahead(channel, PART_ERR))
2764 has_readahead = TRUE;
2765 }
2766 else
2767 {
2768 if (channel_is_open(channel))
2769 return "open";
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002770 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002771 if (channel_has_readahead(channel, part))
2772 {
2773 has_readahead = TRUE;
2774 break;
2775 }
2776 }
Bram Moolenaar437905c2016-04-26 19:01:05 +02002777
2778 if (has_readahead)
2779 return "buffered";
Bram Moolenaar77073442016-02-13 23:23:53 +01002780 return "closed";
2781}
2782
Bram Moolenaar03602ec2016-03-20 20:57:45 +01002783 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002784channel_part_info(channel_T *channel, dict_T *dict, char *name, ch_part_T part)
Bram Moolenaar03602ec2016-03-20 20:57:45 +01002785{
2786 chanpart_T *chanpart = &channel->ch_part[part];
Bram Moolenaar925ccfd2016-03-28 22:38:02 +02002787 char namebuf[20]; /* longest is "sock_timeout" */
Bram Moolenaar3f3fbd32016-03-21 12:36:28 +01002788 size_t tail;
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002789 char *status;
Bram Moolenaar573e4452016-03-21 22:35:10 +01002790 char *s = "";
Bram Moolenaar03602ec2016-03-20 20:57:45 +01002791
Bram Moolenaar925ccfd2016-03-28 22:38:02 +02002792 vim_strncpy((char_u *)namebuf, (char_u *)name, 4);
Bram Moolenaar03602ec2016-03-20 20:57:45 +01002793 STRCAT(namebuf, "_");
2794 tail = STRLEN(namebuf);
2795
2796 STRCPY(namebuf + tail, "status");
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002797 if (chanpart->ch_fd != INVALID_FD)
2798 status = "open";
2799 else if (channel_has_readahead(channel, part))
2800 status = "buffered";
2801 else
2802 status = "closed";
2803 dict_add_nr_str(dict, namebuf, 0, (char_u *)status);
Bram Moolenaar03602ec2016-03-20 20:57:45 +01002804
2805 STRCPY(namebuf + tail, "mode");
2806 switch (chanpart->ch_mode)
2807 {
2808 case MODE_NL: s = "NL"; break;
2809 case MODE_RAW: s = "RAW"; break;
2810 case MODE_JSON: s = "JSON"; break;
2811 case MODE_JS: s = "JS"; break;
2812 }
2813 dict_add_nr_str(dict, namebuf, 0, (char_u *)s);
2814
2815 STRCPY(namebuf + tail, "io");
2816 if (part == PART_SOCK)
2817 s = "socket";
2818 else switch (chanpart->ch_io)
2819 {
2820 case JIO_NULL: s = "null"; break;
2821 case JIO_PIPE: s = "pipe"; break;
2822 case JIO_FILE: s = "file"; break;
2823 case JIO_BUFFER: s = "buffer"; break;
2824 case JIO_OUT: s = "out"; break;
2825 }
2826 dict_add_nr_str(dict, namebuf, 0, (char_u *)s);
2827
2828 STRCPY(namebuf + tail, "timeout");
2829 dict_add_nr_str(dict, namebuf, chanpart->ch_timeout, NULL);
2830}
2831
2832 void
2833channel_info(channel_T *channel, dict_T *dict)
2834{
2835 dict_add_nr_str(dict, "id", channel->ch_id, NULL);
Bram Moolenaar7ef38102016-09-26 22:36:58 +02002836 dict_add_nr_str(dict, "status", 0, (char_u *)channel_status(channel, -1));
Bram Moolenaar03602ec2016-03-20 20:57:45 +01002837
2838 if (channel->ch_hostname != NULL)
2839 {
2840 dict_add_nr_str(dict, "hostname", 0, (char_u *)channel->ch_hostname);
2841 dict_add_nr_str(dict, "port", channel->ch_port, NULL);
2842 channel_part_info(channel, dict, "sock", PART_SOCK);
2843 }
2844 else
2845 {
2846 channel_part_info(channel, dict, "out", PART_OUT);
2847 channel_part_info(channel, dict, "err", PART_ERR);
2848 channel_part_info(channel, dict, "in", PART_IN);
2849 }
2850}
2851
Bram Moolenaar77073442016-02-13 23:23:53 +01002852/*
2853 * Close channel "channel".
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +01002854 * Trigger the close callback if "invoke_close_cb" is TRUE.
Bram Moolenaar187db502016-02-27 14:44:26 +01002855 * Does not clear the buffers.
Bram Moolenaard04a0202016-01-26 23:30:18 +01002856 */
2857 void
Bram Moolenaar8b374212016-02-24 20:43:06 +01002858channel_close(channel_T *channel, int invoke_close_cb)
Bram Moolenaard04a0202016-01-26 23:30:18 +01002859{
Bram Moolenaar81661fb2016-02-18 22:23:34 +01002860 ch_log(channel, "Closing channel");
Bram Moolenaard04a0202016-01-26 23:30:18 +01002861
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01002862#ifdef FEAT_GUI
2863 channel_gui_unregister(channel);
2864#endif
2865
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002866 ch_close_part(channel, PART_SOCK);
2867 ch_close_part(channel, PART_IN);
2868 ch_close_part(channel, PART_OUT);
2869 ch_close_part(channel, PART_ERR);
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01002870
Bram Moolenaara9f02812017-08-05 17:40:38 +02002871 if (invoke_close_cb)
Bram Moolenaar4e221c92016-02-23 13:20:22 +01002872 {
Bram Moolenaara9f02812017-08-05 17:40:38 +02002873 ch_part_T part;
Bram Moolenaar4e221c92016-02-23 13:20:22 +01002874
Bram Moolenaara9f02812017-08-05 17:40:38 +02002875 /* Invoke callbacks and flush buffers before the close callback. */
2876 if (channel->ch_close_cb != NULL)
2877 ch_log(channel,
2878 "Invoking callbacks and flushing buffers before closing");
2879 for (part = PART_SOCK; part < PART_IN; ++part)
2880 {
2881 if (channel->ch_close_cb != NULL
2882 || channel->ch_part[part].ch_bufref.br_buf != NULL)
2883 {
2884 /* Increment the refcount to avoid the channel being freed
2885 * halfway. */
2886 ++channel->ch_refcount;
2887 if (channel->ch_close_cb == NULL)
2888 ch_log(channel, "flushing %s buffers before closing",
2889 part_names[part]);
2890 while (may_invoke_callback(channel, part))
2891 ;
2892 --channel->ch_refcount;
2893 }
2894 }
Bram Moolenaarb2658a12016-04-26 17:16:24 +02002895
Bram Moolenaara9f02812017-08-05 17:40:38 +02002896 if (channel->ch_close_cb != NULL)
2897 {
2898 typval_T argv[1];
2899 typval_T rettv;
2900 int dummy;
2901
2902 /* Increment the refcount to avoid the channel being freed
2903 * halfway. */
2904 ++channel->ch_refcount;
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02002905 ch_log(channel, "Invoking close callback %s",
Bram Moolenaarb2658a12016-04-26 17:16:24 +02002906 (char *)channel->ch_close_cb);
2907 argv[0].v_type = VAR_CHANNEL;
2908 argv[0].vval.v_channel = channel;
2909 call_func(channel->ch_close_cb, (int)STRLEN(channel->ch_close_cb),
Bram Moolenaardf48fb42016-07-22 21:50:18 +02002910 &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
Bram Moolenaar1735bc92016-03-14 23:05:14 +01002911 channel->ch_close_partial, NULL);
Bram Moolenaarb2658a12016-04-26 17:16:24 +02002912 clear_tv(&rettv);
Bram Moolenaarcefe4f92016-05-04 21:49:19 +02002913 channel_need_redraw = TRUE;
Bram Moolenaar4e221c92016-02-23 13:20:22 +01002914
Bram Moolenaara9f02812017-08-05 17:40:38 +02002915 /* the callback is only called once */
2916 free_callback(channel->ch_close_cb, channel->ch_close_partial);
2917 channel->ch_close_cb = NULL;
2918 channel->ch_close_partial = NULL;
Bram Moolenaar437905c2016-04-26 19:01:05 +02002919
Bram Moolenaara9f02812017-08-05 17:40:38 +02002920 if (channel_need_redraw)
2921 {
2922 channel_need_redraw = FALSE;
Bram Moolenaar02e177d2017-08-26 23:43:28 +02002923 redraw_after_callback(TRUE);
Bram Moolenaara9f02812017-08-05 17:40:38 +02002924 }
Bram Moolenaarcefe4f92016-05-04 21:49:19 +02002925
Bram Moolenaara9f02812017-08-05 17:40:38 +02002926 if (!channel->ch_drop_never)
2927 /* any remaining messages are useless now */
2928 for (part = PART_SOCK; part < PART_IN; ++part)
2929 drop_messages(channel, part);
Bram Moolenaar5fd8b782017-11-11 15:54:00 +01002930
2931 --channel->ch_refcount;
Bram Moolenaara9f02812017-08-05 17:40:38 +02002932 }
Bram Moolenaar4e221c92016-02-23 13:20:22 +01002933 }
2934
2935 channel->ch_nb_close_cb = NULL;
Bram Moolenaard85f2712017-07-28 21:51:57 +02002936
2937#ifdef FEAT_TERMINAL
2938 term_channel_closed(channel);
2939#endif
Bram Moolenaare0874f82016-01-24 20:36:41 +01002940}
2941
Bram Moolenaard04a0202016-01-26 23:30:18 +01002942/*
Bram Moolenaar0874a832016-09-01 15:11:51 +02002943 * Close the "in" part channel "channel".
2944 */
2945 void
2946channel_close_in(channel_T *channel)
2947{
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002948 ch_close_part(channel, PART_IN);
Bram Moolenaar0874a832016-09-01 15:11:51 +02002949}
2950
Bram Moolenaaraba680a2017-09-09 16:42:53 +02002951 static void
2952remove_from_writeque(writeq_T *wq, writeq_T *entry)
2953{
2954 ga_clear(&entry->wq_ga);
2955 wq->wq_next = entry->wq_next;
2956 if (wq->wq_next == NULL)
2957 wq->wq_prev = NULL;
2958 else
2959 wq->wq_next->wq_prev = NULL;
Bram Moolenaar5b5adf52017-09-09 18:16:43 +02002960 vim_free(entry);
Bram Moolenaaraba680a2017-09-09 16:42:53 +02002961}
2962
Bram Moolenaar0874a832016-09-01 15:11:51 +02002963/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002964 * Clear the read buffer on "channel"/"part".
Bram Moolenaard04a0202016-01-26 23:30:18 +01002965 */
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002966 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02002967channel_clear_one(channel_T *channel, ch_part_T part)
Bram Moolenaard04a0202016-01-26 23:30:18 +01002968{
Bram Moolenaaraba680a2017-09-09 16:42:53 +02002969 chanpart_T *ch_part = &channel->ch_part[part];
2970 jsonq_T *json_head = &ch_part->ch_json_head;
2971 cbq_T *cb_head = &ch_part->ch_cb_head;
Bram Moolenaard04a0202016-01-26 23:30:18 +01002972
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002973 while (channel_peek(channel, part) != NULL)
2974 vim_free(channel_get(channel, part));
Bram Moolenaar77073442016-02-13 23:23:53 +01002975
2976 while (cb_head->cq_next != NULL)
Bram Moolenaard46ae142016-02-16 13:33:52 +01002977 {
2978 cbq_T *node = cb_head->cq_next;
2979
2980 remove_cb_node(cb_head, node);
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02002981 free_callback(node->cq_callback, node->cq_partial);
Bram Moolenaard46ae142016-02-16 13:33:52 +01002982 vim_free(node);
2983 }
Bram Moolenaar77073442016-02-13 23:23:53 +01002984
2985 while (json_head->jq_next != NULL)
Bram Moolenaard04a0202016-01-26 23:30:18 +01002986 {
Bram Moolenaar77073442016-02-13 23:23:53 +01002987 free_tv(json_head->jq_next->jq_value);
2988 remove_json_node(json_head, json_head->jq_next);
Bram Moolenaard04a0202016-01-26 23:30:18 +01002989 }
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01002990
Bram Moolenaaraba680a2017-09-09 16:42:53 +02002991 free_callback(ch_part->ch_callback, ch_part->ch_partial);
2992 ch_part->ch_callback = NULL;
2993 ch_part->ch_partial = NULL;
2994
2995 while (ch_part->ch_writeque.wq_next != NULL)
2996 remove_from_writeque(&ch_part->ch_writeque,
2997 ch_part->ch_writeque.wq_next);
Bram Moolenaar42d38a22016-02-20 18:18:59 +01002998}
2999
3000/*
3001 * Clear all the read buffers on "channel".
3002 */
3003 void
3004channel_clear(channel_T *channel)
3005{
Bram Moolenaard6051b52016-02-28 15:49:03 +01003006 ch_log(channel, "Clearing channel");
Bram Moolenaard23a8232018-02-10 18:45:26 +01003007 VIM_CLEAR(channel->ch_hostname);
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003008 channel_clear_one(channel, PART_SOCK);
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003009 channel_clear_one(channel, PART_OUT);
3010 channel_clear_one(channel, PART_ERR);
Bram Moolenaar5b5adf52017-09-09 18:16:43 +02003011 channel_clear_one(channel, PART_IN);
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02003012 free_callback(channel->ch_callback, channel->ch_partial);
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01003013 channel->ch_callback = NULL;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01003014 channel->ch_partial = NULL;
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02003015 free_callback(channel->ch_close_cb, channel->ch_close_partial);
Bram Moolenaar4e221c92016-02-23 13:20:22 +01003016 channel->ch_close_cb = NULL;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01003017 channel->ch_close_partial = NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +01003018}
3019
Bram Moolenaar77073442016-02-13 23:23:53 +01003020#if defined(EXITFREE) || defined(PROTO)
3021 void
3022channel_free_all(void)
3023{
3024 channel_T *channel;
3025
Bram Moolenaard6051b52016-02-28 15:49:03 +01003026 ch_log(NULL, "channel_free_all()");
Bram Moolenaar77073442016-02-13 23:23:53 +01003027 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
3028 channel_clear(channel);
3029}
3030#endif
3031
3032
Bram Moolenaar715d2852016-04-30 17:06:31 +02003033/* Sent when the netbeans channel is found closed when reading. */
Bram Moolenaareed284a2016-02-22 23:13:33 +01003034#define DETACH_MSG_RAW "DETACH\n"
Bram Moolenaard04a0202016-01-26 23:30:18 +01003035
3036/* Buffer size for reading incoming messages. */
3037#define MAXMSGSIZE 4096
3038
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003039#if defined(HAVE_SELECT)
3040/*
3041 * Add write fds where we are waiting for writing to be possible.
3042 */
3043 static int
3044channel_fill_wfds(int maxfd_arg, fd_set *wfds)
3045{
3046 int maxfd = maxfd_arg;
3047 channel_T *ch;
3048
3049 for (ch = first_channel; ch != NULL; ch = ch->ch_next)
3050 {
3051 chanpart_T *in_part = &ch->ch_part[PART_IN];
3052
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003053 if (in_part->ch_fd != INVALID_FD
3054 && (in_part->ch_bufref.br_buf != NULL
3055 || in_part->ch_writeque.wq_next != NULL))
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003056 {
3057 FD_SET((int)in_part->ch_fd, wfds);
3058 if ((int)in_part->ch_fd >= maxfd)
3059 maxfd = (int)in_part->ch_fd + 1;
3060 }
3061 }
3062 return maxfd;
3063}
3064#else
3065/*
3066 * Add write fds where we are waiting for writing to be possible.
3067 */
3068 static int
3069channel_fill_poll_write(int nfd_in, struct pollfd *fds)
3070{
3071 int nfd = nfd_in;
3072 channel_T *ch;
3073
3074 for (ch = first_channel; ch != NULL; ch = ch->ch_next)
3075 {
3076 chanpart_T *in_part = &ch->ch_part[PART_IN];
3077
Bram Moolenaar683b7962017-08-19 15:51:59 +02003078 if (in_part->ch_fd != INVALID_FD
3079 && (in_part->ch_bufref.br_buf != NULL
3080 || in_part->ch_writeque.wq_next != NULL))
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003081 {
3082 in_part->ch_poll_idx = nfd;
3083 fds[nfd].fd = in_part->ch_fd;
3084 fds[nfd].events = POLLOUT;
3085 ++nfd;
3086 }
3087 else
3088 in_part->ch_poll_idx = -1;
3089 }
3090 return nfd;
3091}
3092#endif
3093
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003094typedef enum {
3095 CW_READY,
3096 CW_NOT_READY,
3097 CW_ERROR
3098} channel_wait_result;
3099
Bram Moolenaard04a0202016-01-26 23:30:18 +01003100/*
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003101 * Check for reading from "fd" with "timeout" msec.
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003102 * Return CW_READY when there is something to read.
3103 * Return CW_NOT_READY when there is nothing to read.
3104 * Return CW_ERROR when there is an error.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003105 */
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003106 static channel_wait_result
Bram Moolenaard8070362016-02-15 21:56:54 +01003107channel_wait(channel_T *channel, sock_T fd, int timeout)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003108{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003109 if (timeout > 0)
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003110 ch_log(channel, "Waiting for up to %d msec", timeout);
Bram Moolenaard8070362016-02-15 21:56:54 +01003111
Bram Moolenaard8070362016-02-15 21:56:54 +01003112# ifdef WIN32
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003113 if (fd != channel->CH_SOCK_FD)
Bram Moolenaard8070362016-02-15 21:56:54 +01003114 {
3115 DWORD nread;
Bram Moolenaar84e1d2b2016-03-28 14:20:41 +02003116 int sleep_time;
Bram Moolenaard8070362016-02-15 21:56:54 +01003117 DWORD deadline = GetTickCount() + timeout;
Bram Moolenaar84e1d2b2016-03-28 14:20:41 +02003118 int delay = 1;
Bram Moolenaard8070362016-02-15 21:56:54 +01003119
3120 /* reading from a pipe, not a socket */
3121 while (TRUE)
3122 {
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003123 int r = PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL);
3124
3125 if (r && nread > 0)
3126 return CW_READY;
3127 if (r == 0)
Bram Moolenaar2dc9d262017-09-08 14:39:30 +02003128 {
3129 DWORD err = GetLastError();
3130
3131 if (err != ERROR_BAD_PIPE && err != ERROR_BROKEN_PIPE)
3132 return CW_ERROR;
3133
3134 if (channel->ch_named_pipe)
3135 {
3136 DisconnectNamedPipe((HANDLE)fd);
3137 ConnectNamedPipe((HANDLE)fd, NULL);
3138 }
3139 else
3140 return CW_ERROR;
3141 }
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003142
3143 /* perhaps write some buffer lines */
3144 channel_write_any_lines();
3145
Bram Moolenaar84e1d2b2016-03-28 14:20:41 +02003146 sleep_time = deadline - GetTickCount();
3147 if (sleep_time <= 0)
Bram Moolenaard8070362016-02-15 21:56:54 +01003148 break;
Bram Moolenaar84e1d2b2016-03-28 14:20:41 +02003149 /* Wait for a little while. Very short at first, up to 10 msec
3150 * after looping a few times. */
3151 if (sleep_time > delay)
3152 sleep_time = delay;
3153 Sleep(sleep_time);
3154 delay = delay * 2;
3155 if (delay > 10)
3156 delay = 10;
Bram Moolenaard8070362016-02-15 21:56:54 +01003157 }
Bram Moolenaard8070362016-02-15 21:56:54 +01003158 }
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003159 else
Bram Moolenaard8070362016-02-15 21:56:54 +01003160#endif
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003161 {
Bram Moolenaar9186a272016-02-23 19:34:01 +01003162#if defined(HAVE_SELECT)
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003163 struct timeval tval;
3164 fd_set rfds;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003165 fd_set wfds;
3166 int ret;
3167 int maxfd;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003168
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003169 tval.tv_sec = timeout / 1000;
3170 tval.tv_usec = (timeout % 1000) * 1000;
3171 for (;;)
3172 {
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003173 FD_ZERO(&rfds);
3174 FD_SET((int)fd, &rfds);
3175
3176 /* Write lines to a pipe when a pipe can be written to. Need to
3177 * set this every time, some buffers may be done. */
3178 maxfd = (int)fd + 1;
3179 FD_ZERO(&wfds);
3180 maxfd = channel_fill_wfds(maxfd, &wfds);
3181
3182 ret = select(maxfd, &rfds, &wfds, NULL, &tval);
Bram Moolenaar9186a272016-02-23 19:34:01 +01003183# ifdef EINTR
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003184 SOCK_ERRNO;
3185 if (ret == -1 && errno == EINTR)
3186 continue;
Bram Moolenaar9186a272016-02-23 19:34:01 +01003187# endif
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003188 if (ret > 0)
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003189 {
3190 if (FD_ISSET(fd, &rfds))
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003191 return CW_READY;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003192 channel_write_any_lines();
3193 continue;
3194 }
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003195 break;
3196 }
Bram Moolenaar9186a272016-02-23 19:34:01 +01003197#else
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003198 for (;;)
3199 {
3200 struct pollfd fds[MAX_OPEN_CHANNELS + 1];
3201 int nfd = 1;
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003202
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003203 fds[0].fd = fd;
3204 fds[0].events = POLLIN;
3205 nfd = channel_fill_poll_write(nfd, fds);
3206 if (poll(fds, nfd, timeout) > 0)
3207 {
3208 if (fds[0].revents & POLLIN)
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003209 return CW_READY;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02003210 channel_write_any_lines();
3211 continue;
3212 }
3213 break;
3214 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003215#endif
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003216 }
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003217 return CW_NOT_READY;
3218}
3219
3220 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003221ch_close_part_on_error(
3222 channel_T *channel, ch_part_T part, int is_err, char *func)
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003223{
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003224 char msg[] = "%s(): Read %s from ch_part[%d], closing";
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003225
3226 if (is_err)
3227 /* Do not call emsg(), most likely the other end just exited. */
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003228 ch_error(channel, msg, func, "error", part);
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003229 else
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003230 ch_log(channel, msg, func, "EOF", part);
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003231
3232 /* Queue a "DETACH" netbeans message in the command queue in order to
3233 * terminate the netbeans session later. Do not end the session here
3234 * directly as we may be running in the context of a call to
3235 * netbeans_parse_messages():
3236 * netbeans_parse_messages
3237 * -> autocmd triggered while processing the netbeans cmd
3238 * -> ui_breakcheck
3239 * -> gui event loop or select loop
3240 * -> channel_read()
Bram Moolenaar715d2852016-04-30 17:06:31 +02003241 * Only send "DETACH" for a netbeans channel.
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003242 */
Bram Moolenaar715d2852016-04-30 17:06:31 +02003243 if (channel->ch_nb_close_cb != NULL)
Bram Moolenaar8ddef482016-10-09 15:43:25 +02003244 channel_save(channel, PART_SOCK, (char_u *)DETACH_MSG_RAW,
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003245 (int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT ");
3246
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003247 /* When reading is not possible close this part of the channel. Don't
3248 * close the channel yet, there may be something to read on another part. */
3249 ch_close_part(channel, part);
Bram Moolenaarbf981ee2016-05-28 13:20:31 +02003250
3251#ifdef FEAT_GUI
3252 /* Stop listening to GUI events right away. */
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003253 channel_gui_unregister_one(channel, part);
Bram Moolenaarbf981ee2016-05-28 13:20:31 +02003254#endif
Bram Moolenaarcf7ff702016-05-09 17:20:14 +02003255}
3256
3257 static void
3258channel_close_now(channel_T *channel)
3259{
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003260 ch_log(channel, "Closing channel because all readable fds are closed");
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003261 if (channel->ch_nb_close_cb != NULL)
3262 (*channel->ch_nb_close_cb)();
Bram Moolenaar958dc692016-12-01 15:34:12 +01003263 channel_close(channel, TRUE);
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003264}
3265
3266/*
Bram Moolenaar77073442016-02-13 23:23:53 +01003267 * Read from channel "channel" for as long as there is something to read.
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003268 * "part" is PART_SOCK, PART_OUT or PART_ERR.
Bram Moolenaar655da312016-05-28 22:22:34 +02003269 * The data is put in the read queue. No callbacks are invoked here.
Bram Moolenaard04a0202016-01-26 23:30:18 +01003270 */
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003271 static void
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003272channel_read(channel_T *channel, ch_part_T part, char *func)
Bram Moolenaard04a0202016-01-26 23:30:18 +01003273{
3274 static char_u *buf = NULL;
3275 int len = 0;
3276 int readlen = 0;
Bram Moolenaard8070362016-02-15 21:56:54 +01003277 sock_T fd;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003278 int use_socket = FALSE;
Bram Moolenaard04a0202016-01-26 23:30:18 +01003279
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003280 fd = channel->ch_part[part].ch_fd;
3281 if (fd == INVALID_FD)
3282 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003283 ch_error(channel, "channel_read() called while %s part is closed",
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003284 part_names[part]);
Bram Moolenaard04a0202016-01-26 23:30:18 +01003285 return;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003286 }
3287 use_socket = fd == channel->CH_SOCK_FD;
Bram Moolenaard04a0202016-01-26 23:30:18 +01003288
3289 /* Allocate a buffer to read into. */
3290 if (buf == NULL)
3291 {
3292 buf = alloc(MAXMSGSIZE);
3293 if (buf == NULL)
3294 return; /* out of memory! */
3295 }
3296
3297 /* Keep on reading for as long as there is something to read.
3298 * Use select() or poll() to avoid blocking on a message that is exactly
3299 * MAXMSGSIZE long. */
3300 for (;;)
3301 {
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003302 if (channel_wait(channel, fd, 0) != CW_READY)
Bram Moolenaard04a0202016-01-26 23:30:18 +01003303 break;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003304 if (use_socket)
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01003305 len = sock_read(fd, (char *)buf, MAXMSGSIZE);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003306 else
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01003307 len = fd_read(fd, (char *)buf, MAXMSGSIZE);
Bram Moolenaard04a0202016-01-26 23:30:18 +01003308 if (len <= 0)
3309 break; /* error or nothing more to read */
3310
3311 /* Store the read message in the queue. */
Bram Moolenaar46c00a62016-03-28 14:11:42 +02003312 channel_save(channel, part, buf, len, FALSE, "RECV ");
Bram Moolenaard04a0202016-01-26 23:30:18 +01003313 readlen += len;
3314 if (len < MAXMSGSIZE)
3315 break; /* did read everything that's available */
3316 }
3317
Bram Moolenaar4cafa6d2016-02-26 11:52:39 +01003318 /* Reading a disconnection (readlen == 0), or an error. */
Bram Moolenaarbd73ae12016-02-22 22:19:22 +01003319 if (readlen <= 0)
Bram Moolenaar13ebb032017-08-26 22:02:51 +02003320 {
3321 if (!channel->ch_keep_open)
3322 ch_close_part_on_error(channel, part, (len < 0), func);
3323 }
Bram Moolenaard04a0202016-01-26 23:30:18 +01003324#if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK)
Bram Moolenaar13ebb032017-08-26 22:02:51 +02003325 else if (CH_HAS_GUI && gtk_main_level() > 0)
3326 /* signal the main loop that there is something to read */
Bram Moolenaard04a0202016-01-26 23:30:18 +01003327 gtk_main_quit();
3328#endif
3329}
3330
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003331/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003332 * Read from RAW or NL "channel"/"part". Blocks until there is something to
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003333 * read or the timeout expires.
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003334 * When "raw" is TRUE don't block waiting on a NL.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003335 * Returns what was read in allocated memory.
3336 * Returns NULL in case of error or timeout.
3337 */
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003338 static char_u *
3339channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003340{
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003341 char_u *buf;
3342 char_u *msg;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003343 ch_mode_T mode = channel->ch_part[part].ch_mode;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003344 sock_T fd = channel->ch_part[part].ch_fd;
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003345 char_u *nl;
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02003346 readq_T *node;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003347
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003348 ch_log(channel, "Blocking %s read, timeout: %d msec",
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003349 mode == MODE_RAW ? "RAW" : "NL", timeout);
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003350
3351 while (TRUE)
3352 {
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02003353 node = channel_peek(channel, part);
3354 if (node != NULL)
3355 {
3356 if (mode == MODE_RAW || (mode == MODE_NL
3357 && channel_first_nl(node) != NULL))
3358 /* got a complete message */
3359 break;
3360 if (channel_collapse(channel, part, mode == MODE_NL) == OK)
3361 continue;
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003362 /* If not blocking or nothing more is coming then return what we
3363 * have. */
3364 if (raw || fd == INVALID_FD)
3365 break;
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02003366 }
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003367
Bram Moolenaar4d919d72016-02-05 22:36:41 +01003368 /* Wait for up to the channel timeout. */
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003369 if (fd == INVALID_FD)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003370 return NULL;
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003371 if (channel_wait(channel, fd, timeout) != CW_READY)
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003372 {
3373 ch_log(channel, "Timed out");
3374 return NULL;
3375 }
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003376 channel_read(channel, part, "channel_read_block");
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003377 }
3378
Bram Moolenaarb113c3a2017-02-28 21:26:17 +01003379 /* We have a complete message now. */
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003380 if (mode == MODE_RAW)
3381 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003382 msg = channel_get_all(channel, part);
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003383 }
3384 else
3385 {
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02003386 char_u *p;
3387
3388 buf = node->rq_buffer;
3389 nl = channel_first_nl(node);
3390
3391 /* Convert NUL to NL, the internal representation. */
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003392 for (p = buf; (nl == NULL || p < nl) && p < buf + node->rq_buflen; ++p)
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02003393 if (*p == NUL)
3394 *p = NL;
3395
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003396 if (nl == NULL)
3397 {
3398 /* must be a closed channel with missing NL */
3399 msg = channel_get(channel, part);
3400 }
3401 else if (nl + 1 == buf + node->rq_buflen)
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003402 {
3403 /* get the whole buffer */
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003404 msg = channel_get(channel, part);
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003405 *nl = NUL;
3406 }
3407 else
3408 {
3409 /* Copy the message into allocated memory and remove it from the
3410 * buffer. */
3411 msg = vim_strnsave(buf, (int)(nl - buf));
Bram Moolenaar5f1032d2016-06-07 22:16:36 +02003412 channel_consume(channel, part, (int)(nl - buf) + 1);
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003413 }
3414 }
Bram Moolenaar71eeb742017-09-13 22:18:01 +02003415 if (ch_log_active())
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003416 ch_log(channel, "Returning %d bytes", (int)STRLEN(msg));
Bram Moolenaar9a6e33a2016-02-16 19:25:12 +01003417 return msg;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003418}
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003419
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003420/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003421 * Read one JSON message with ID "id" from "channel"/"part" and store the
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003422 * result in "rettv".
Bram Moolenaar6f3a5442016-02-20 19:56:13 +01003423 * When "id" is -1 accept any message;
Bram Moolenaar4d919d72016-02-05 22:36:41 +01003424 * Blocks until the message is received or the timeout is reached.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003425 */
Bram Moolenaar958dc692016-12-01 15:34:12 +01003426 static int
Bram Moolenaar6f3a5442016-02-20 19:56:13 +01003427channel_read_json_block(
Bram Moolenaard6051b52016-02-28 15:49:03 +01003428 channel_T *channel,
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003429 ch_part_T part,
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003430 int timeout_arg,
Bram Moolenaard6051b52016-02-28 15:49:03 +01003431 int id,
3432 typval_T **rettv)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003433{
Bram Moolenaare56bf152016-02-08 23:23:42 +01003434 int more;
Bram Moolenaard8070362016-02-15 21:56:54 +01003435 sock_T fd;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003436 int timeout;
3437 chanpart_T *chanpart = &channel->ch_part[part];
Bram Moolenaard7ece102016-02-02 23:23:02 +01003438
Bram Moolenaar81661fb2016-02-18 22:23:34 +01003439 ch_log(channel, "Reading JSON");
Bram Moolenaar6f3a5442016-02-20 19:56:13 +01003440 if (id != -1)
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003441 chanpart->ch_block_id = id;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003442 for (;;)
3443 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003444 more = channel_parse_json(channel, part);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003445
Bram Moolenaaraad30bb2016-06-26 17:31:03 +02003446 /* search for message "id" */
Bram Moolenaar958dc692016-12-01 15:34:12 +01003447 if (channel_get_json(channel, part, id, TRUE, rettv) == OK)
Bram Moolenaare56bf152016-02-08 23:23:42 +01003448 {
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003449 chanpart->ch_block_id = 0;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003450 return OK;
Bram Moolenaare56bf152016-02-08 23:23:42 +01003451 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003452
Bram Moolenaard7ece102016-02-02 23:23:02 +01003453 if (!more)
3454 {
3455 /* Handle any other messages in the queue. If done some more
3456 * messages may have arrived. */
3457 if (channel_parse_messages())
3458 continue;
3459
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003460 /* Wait for up to the timeout. If there was an incomplete message
3461 * use the deadline for that. */
3462 timeout = timeout_arg;
Bram Moolenaar88989cc2017-02-06 21:56:09 +01003463 if (chanpart->ch_wait_len > 0)
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003464 {
3465#ifdef WIN32
3466 timeout = chanpart->ch_deadline - GetTickCount() + 1;
3467#else
3468 {
3469 struct timeval now_tv;
3470
3471 gettimeofday(&now_tv, NULL);
3472 timeout = (chanpart->ch_deadline.tv_sec
3473 - now_tv.tv_sec) * 1000
3474 + (chanpart->ch_deadline.tv_usec
3475 - now_tv.tv_usec) / 1000
3476 + 1;
3477 }
3478#endif
3479 if (timeout < 0)
3480 {
3481 /* Something went wrong, channel_parse_json() didn't
3482 * discard message. Cancel waiting. */
Bram Moolenaar88989cc2017-02-06 21:56:09 +01003483 chanpart->ch_wait_len = 0;
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003484 timeout = timeout_arg;
3485 }
3486 else if (timeout > timeout_arg)
3487 timeout = timeout_arg;
3488 }
3489 fd = chanpart->ch_fd;
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003490 if (fd == INVALID_FD
3491 || channel_wait(channel, fd, timeout) != CW_READY)
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003492 {
3493 if (timeout == timeout_arg)
3494 {
3495 if (fd != INVALID_FD)
3496 ch_log(channel, "Timed out");
3497 break;
3498 }
3499 }
3500 else
3501 channel_read(channel, part, "channel_read_json_block");
Bram Moolenaard7ece102016-02-02 23:23:02 +01003502 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003503 }
Bram Moolenaarba61ac02016-03-20 16:40:37 +01003504 chanpart->ch_block_id = 0;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01003505 return FAIL;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003506}
3507
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003508/*
3509 * Common for ch_read() and ch_readraw().
3510 */
3511 void
3512common_channel_read(typval_T *argvars, typval_T *rettv, int raw)
3513{
3514 channel_T *channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003515 ch_part_T part = PART_COUNT;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003516 jobopt_T opt;
3517 int mode;
3518 int timeout;
3519 int id = -1;
3520 typval_T *listtv = NULL;
3521
3522 /* return an empty string by default */
3523 rettv->v_type = VAR_STRING;
3524 rettv->vval.v_string = NULL;
3525
3526 clear_job_options(&opt);
Bram Moolenaar08d384f2017-08-11 21:51:23 +02003527 if (get_job_options(&argvars[1], &opt, JO_TIMEOUT + JO_PART + JO_ID, 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003528 == FAIL)
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02003529 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003530
Bram Moolenaar437905c2016-04-26 19:01:05 +02003531 if (opt.jo_set & JO_PART)
3532 part = opt.jo_part;
3533 channel = get_channel_arg(&argvars[0], TRUE, TRUE, part);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003534 if (channel != NULL)
3535 {
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003536 if (part == PART_COUNT)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003537 part = channel_part_read(channel);
3538 mode = channel_get_mode(channel, part);
3539 timeout = channel_get_timeout(channel, part);
3540 if (opt.jo_set & JO_TIMEOUT)
3541 timeout = opt.jo_timeout;
3542
3543 if (raw || mode == MODE_RAW || mode == MODE_NL)
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003544 rettv->vval.v_string = channel_read_block(channel, part,
3545 timeout, raw);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003546 else
3547 {
3548 if (opt.jo_set & JO_ID)
3549 id = opt.jo_id;
3550 channel_read_json_block(channel, part, timeout, id, &listtv);
3551 if (listtv != NULL)
3552 {
3553 *rettv = *listtv;
3554 vim_free(listtv);
3555 }
3556 else
3557 {
3558 rettv->v_type = VAR_SPECIAL;
3559 rettv->vval.v_number = VVAL_NONE;
3560 }
3561 }
3562 }
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02003563
3564theend:
3565 free_job_options(&opt);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003566}
3567
Bram Moolenaarfffd5562016-02-20 18:44:39 +01003568# if defined(WIN32) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \
3569 || defined(PROTO)
Bram Moolenaar85be35f2016-01-27 21:08:18 +01003570/*
Bram Moolenaarfffd5562016-02-20 18:44:39 +01003571 * Lookup the channel from the socket. Set "partp" to the fd index.
Bram Moolenaar77073442016-02-13 23:23:53 +01003572 * Returns NULL when the socket isn't found.
Bram Moolenaar85be35f2016-01-27 21:08:18 +01003573 */
Bram Moolenaar77073442016-02-13 23:23:53 +01003574 channel_T *
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003575channel_fd2channel(sock_T fd, ch_part_T *partp)
Bram Moolenaar85be35f2016-01-27 21:08:18 +01003576{
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01003577 channel_T *channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003578 ch_part_T part;
Bram Moolenaar85be35f2016-01-27 21:08:18 +01003579
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003580 if (fd != INVALID_FD)
Bram Moolenaar77073442016-02-13 23:23:53 +01003581 for (channel = first_channel; channel != NULL;
3582 channel = channel->ch_next)
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01003583 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003584 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003585 if (channel->ch_part[part].ch_fd == fd)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01003586 {
Bram Moolenaarfffd5562016-02-20 18:44:39 +01003587 *partp = part;
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01003588 return channel;
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01003589 }
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01003590 }
Bram Moolenaar77073442016-02-13 23:23:53 +01003591 return NULL;
Bram Moolenaar85be35f2016-01-27 21:08:18 +01003592}
Bram Moolenaarb7522a22016-02-21 17:20:55 +01003593# endif
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003594
Bram Moolenaar13ebb032017-08-26 22:02:51 +02003595# if defined(WIN32) || defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaarb7522a22016-02-21 17:20:55 +01003596/*
3597 * Check the channels for anything that is ready to be read.
3598 * The data is put in the read queue.
Bram Moolenaar13ebb032017-08-26 22:02:51 +02003599 * if "only_keep_open" is TRUE only check channels where ch_keep_open is set.
Bram Moolenaarb7522a22016-02-21 17:20:55 +01003600 */
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003601 void
Bram Moolenaar13ebb032017-08-26 22:02:51 +02003602channel_handle_events(int only_keep_open)
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003603{
3604 channel_T *channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003605 ch_part_T part;
Bram Moolenaarb7522a22016-02-21 17:20:55 +01003606 sock_T fd;
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003607
3608 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
3609 {
Bram Moolenaar13ebb032017-08-26 22:02:51 +02003610 if (only_keep_open && !channel->ch_keep_open)
3611 continue;
3612
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003613 /* check the socket and pipes */
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003614 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaarb7522a22016-02-21 17:20:55 +01003615 {
3616 fd = channel->ch_part[part].ch_fd;
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003617 if (fd != INVALID_FD)
3618 {
3619 int r = channel_wait(channel, fd, 0);
3620
3621 if (r == CW_READY)
3622 channel_read(channel, part, "channel_handle_events");
3623 else if (r == CW_ERROR)
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003624 ch_close_part_on_error(channel, part, TRUE,
3625 "channel_handle_events");
Bram Moolenaarb2658a12016-04-26 17:16:24 +02003626 }
Bram Moolenaarb7522a22016-02-21 17:20:55 +01003627 }
Bram Moolenaared5a78e2016-02-19 21:05:03 +01003628 }
3629}
Bram Moolenaar85be35f2016-01-27 21:08:18 +01003630# endif
3631
Bram Moolenaar4ab79682017-08-27 14:50:47 +02003632# if defined(FEAT_GUI) || defined(PROTO)
3633/*
3634 * Return TRUE when there is any channel with a keep_open flag.
3635 */
3636 int
3637channel_any_keep_open()
3638{
3639 channel_T *channel;
3640
3641 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
3642 if (channel->ch_keep_open)
3643 return TRUE;
3644 return FALSE;
3645}
3646# endif
3647
Bram Moolenaard04a0202016-01-26 23:30:18 +01003648/*
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003649 * Set "channel"/"part" to non-blocking.
Bram Moolenaarf66a2cd2017-08-18 21:53:22 +02003650 * Only works for sockets and pipes.
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003651 */
3652 void
3653channel_set_nonblock(channel_T *channel, ch_part_T part)
3654{
3655 chanpart_T *ch_part = &channel->ch_part[part];
3656 int fd = ch_part->ch_fd;
3657
3658 if (fd != INVALID_FD)
3659 {
3660#ifdef _WIN32
Bram Moolenaarf66a2cd2017-08-18 21:53:22 +02003661 u_long val = 1;
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003662
Bram Moolenaarf66a2cd2017-08-18 21:53:22 +02003663 ioctlsocket(fd, FIONBIO, &val);
3664#else
Bram Moolenaardc926dd2017-08-19 21:26:44 +02003665 (void)fcntl(fd, F_SETFL, O_NONBLOCK);
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003666#endif
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003667 ch_part->ch_nonblocking = TRUE;
3668 }
3669}
3670
3671/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003672 * Write "buf" (NUL terminated string) to "channel"/"part".
Bram Moolenaard04a0202016-01-26 23:30:18 +01003673 * When "fun" is not NULL an error message might be given.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003674 * Return FAIL or OK.
Bram Moolenaard04a0202016-01-26 23:30:18 +01003675 */
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003676 int
Bram Moolenaar79cbdcb2016-11-11 21:14:03 +01003677channel_send(
3678 channel_T *channel,
3679 ch_part_T part,
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003680 char_u *buf_arg,
3681 int len_arg,
Bram Moolenaar79cbdcb2016-11-11 21:14:03 +01003682 char *fun)
Bram Moolenaard04a0202016-01-26 23:30:18 +01003683{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003684 int res;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003685 sock_T fd;
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003686 chanpart_T *ch_part = &channel->ch_part[part];
3687 int did_use_queue = FALSE;
Bram Moolenaard04a0202016-01-26 23:30:18 +01003688
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003689 fd = ch_part->ch_fd;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01003690 if (fd == INVALID_FD)
Bram Moolenaard04a0202016-01-26 23:30:18 +01003691 {
3692 if (!channel->ch_error && fun != NULL)
3693 {
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02003694 ch_error(channel, "%s(): write while not connected", fun);
Bram Moolenaar5b302912016-08-24 22:11:55 +02003695 EMSG2(_("E630: %s(): write while not connected"), fun);
Bram Moolenaard04a0202016-01-26 23:30:18 +01003696 }
3697 channel->ch_error = TRUE;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003698 return FAIL;
Bram Moolenaard04a0202016-01-26 23:30:18 +01003699 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003700
Bram Moolenaar71eeb742017-09-13 22:18:01 +02003701 if (ch_log_active())
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003702 {
Bram Moolenaar77073442016-02-13 23:23:53 +01003703 ch_log_lead("SEND ", channel);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003704 fprintf(log_fd, "'");
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003705 ignored = (int)fwrite(buf_arg, len_arg, 1, log_fd);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003706 fprintf(log_fd, "'\n");
3707 fflush(log_fd);
Bram Moolenaard0b65022016-03-06 21:50:33 +01003708 did_log_msg = TRUE;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01003709 }
3710
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003711 for (;;)
Bram Moolenaard04a0202016-01-26 23:30:18 +01003712 {
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003713 writeq_T *wq = &ch_part->ch_writeque;
3714 char_u *buf;
3715 int len;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003716
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003717 if (wq->wq_next != NULL)
3718 {
3719 /* first write what was queued */
3720 buf = wq->wq_next->wq_ga.ga_data;
3721 len = wq->wq_next->wq_ga.ga_len;
3722 did_use_queue = TRUE;
3723 }
3724 else
3725 {
3726 if (len_arg == 0)
3727 /* nothing to write, called from channel_select_check() */
3728 return OK;
3729 buf = buf_arg;
3730 len = len_arg;
3731 }
3732
3733 if (part == PART_SOCK)
3734 res = sock_write(fd, (char *)buf, len);
3735 else
Bram Moolenaar2dc9d262017-09-08 14:39:30 +02003736 {
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003737 res = fd_write(fd, (char *)buf, len);
Bram Moolenaar2dc9d262017-09-08 14:39:30 +02003738#ifdef WIN32
Bram Moolenaar3c518402017-09-08 20:47:00 +02003739 if (channel->ch_named_pipe && res < 0)
Bram Moolenaar2dc9d262017-09-08 14:39:30 +02003740 {
Bram Moolenaar3c518402017-09-08 20:47:00 +02003741 DisconnectNamedPipe((HANDLE)fd);
3742 ConnectNamedPipe((HANDLE)fd, NULL);
Bram Moolenaar2dc9d262017-09-08 14:39:30 +02003743 }
3744#endif
3745
3746 }
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003747 if (res < 0 && (errno == EWOULDBLOCK
3748#ifdef EAGAIN
3749 || errno == EAGAIN
3750#endif
3751 ))
3752 res = 0; /* nothing got written */
3753
3754 if (res >= 0 && ch_part->ch_nonblocking)
3755 {
3756 writeq_T *entry = wq->wq_next;
3757
3758 if (did_use_queue)
3759 ch_log(channel, "Sent %d bytes now", res);
3760 if (res == len)
3761 {
3762 /* Wrote all the buf[len] bytes. */
3763 if (entry != NULL)
3764 {
3765 /* Remove the entry from the write queue. */
Bram Moolenaaraba680a2017-09-09 16:42:53 +02003766 remove_from_writeque(wq, entry);
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003767 continue;
3768 }
3769 if (did_use_queue)
3770 ch_log(channel, "Write queue empty");
3771 }
3772 else
3773 {
3774 /* Wrote only buf[res] bytes, can't write more now. */
3775 if (entry != NULL)
3776 {
3777 if (res > 0)
3778 {
3779 /* Remove the bytes that were written. */
3780 mch_memmove(entry->wq_ga.ga_data,
3781 (char *)entry->wq_ga.ga_data + res,
3782 len - res);
3783 entry->wq_ga.ga_len -= res;
3784 }
3785 buf = buf_arg;
3786 len = len_arg;
3787 }
3788 else
3789 {
3790 buf += res;
3791 len -= res;
3792 }
3793 ch_log(channel, "Adding %d bytes to the write queue", len);
3794
3795 /* Append the not written bytes of the argument to the write
3796 * buffer. Limit entries to 4000 bytes. */
3797 if (wq->wq_prev != NULL
3798 && wq->wq_prev->wq_ga.ga_len + len < 4000)
3799 {
3800 writeq_T *last = wq->wq_prev;
3801
3802 /* append to the last entry */
3803 if (ga_grow(&last->wq_ga, len) == OK)
3804 {
3805 mch_memmove((char *)last->wq_ga.ga_data
3806 + last->wq_ga.ga_len,
3807 buf, len);
3808 last->wq_ga.ga_len += len;
3809 }
3810 }
3811 else
3812 {
3813 writeq_T *last = (writeq_T *)alloc((int)sizeof(writeq_T));
3814
3815 if (last != NULL)
3816 {
Bram Moolenaar97bd5e62017-08-18 20:50:30 +02003817 last->wq_prev = wq->wq_prev;
3818 last->wq_next = NULL;
3819 if (wq->wq_prev == NULL)
3820 wq->wq_next = last;
3821 else
3822 wq->wq_prev->wq_next = last;
3823 wq->wq_prev = last;
3824 ga_init2(&last->wq_ga, 1, 1000);
3825 if (ga_grow(&last->wq_ga, len) == OK)
3826 {
3827 mch_memmove(last->wq_ga.ga_data, buf, len);
3828 last->wq_ga.ga_len = len;
3829 }
3830 }
3831 }
3832 }
3833 }
3834 else if (res != len)
3835 {
3836 if (!channel->ch_error && fun != NULL)
3837 {
3838 ch_error(channel, "%s(): write failed", fun);
3839 EMSG2(_("E631: %s(): write failed"), fun);
3840 }
3841 channel->ch_error = TRUE;
3842 return FAIL;
3843 }
3844
3845 channel->ch_error = FALSE;
3846 return OK;
3847 }
Bram Moolenaard04a0202016-01-26 23:30:18 +01003848}
3849
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003850/*
3851 * Common for "ch_sendexpr()" and "ch_sendraw()".
3852 * Returns the channel if the caller should read the response.
Bram Moolenaaraad30bb2016-06-26 17:31:03 +02003853 * Sets "part_read" to the read fd.
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003854 * Otherwise returns NULL.
3855 */
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003856 static channel_T *
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003857send_common(
3858 typval_T *argvars,
3859 char_u *text,
3860 int id,
3861 int eval,
3862 jobopt_T *opt,
3863 char *fun,
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003864 ch_part_T *part_read)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003865{
3866 channel_T *channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003867 ch_part_T part_send;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003868
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02003869 clear_job_options(opt);
Bram Moolenaar437905c2016-04-26 19:01:05 +02003870 channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003871 if (channel == NULL)
3872 return NULL;
3873 part_send = channel_part_send(channel);
3874 *part_read = channel_part_read(channel);
3875
Bram Moolenaar08d384f2017-08-11 21:51:23 +02003876 if (get_job_options(&argvars[2], opt, JO_CALLBACK + JO_TIMEOUT, 0) == FAIL)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003877 return NULL;
3878
3879 /* Set the callback. An empty callback means no callback and not reading
3880 * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not
3881 * allowed. */
3882 if (opt->jo_callback != NULL && *opt->jo_callback != NUL)
3883 {
3884 if (eval)
3885 {
3886 EMSG2(_("E917: Cannot use a callback with %s()"), fun);
3887 return NULL;
3888 }
Bram Moolenaar6fc82272016-08-28 19:26:43 +02003889 channel_set_req_callback(channel, *part_read,
Bram Moolenaar1735bc92016-03-14 23:05:14 +01003890 opt->jo_callback, opt->jo_partial, id);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003891 }
3892
Bram Moolenaarbf2cc5f2016-07-07 20:45:06 +02003893 if (channel_send(channel, part_send, text, (int)STRLEN(text), fun) == OK
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003894 && opt->jo_callback == NULL)
3895 return channel;
3896 return NULL;
3897}
3898
3899/*
3900 * common for "ch_evalexpr()" and "ch_sendexpr()"
3901 */
3902 void
3903ch_expr_common(typval_T *argvars, typval_T *rettv, int eval)
3904{
3905 char_u *text;
3906 typval_T *listtv;
3907 channel_T *channel;
3908 int id;
3909 ch_mode_T ch_mode;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003910 ch_part_T part_send;
3911 ch_part_T part_read;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003912 jobopt_T opt;
3913 int timeout;
3914
3915 /* return an empty string by default */
3916 rettv->v_type = VAR_STRING;
3917 rettv->vval.v_string = NULL;
3918
Bram Moolenaar437905c2016-04-26 19:01:05 +02003919 channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003920 if (channel == NULL)
3921 return;
3922 part_send = channel_part_send(channel);
3923
3924 ch_mode = channel_get_mode(channel, part_send);
3925 if (ch_mode == MODE_RAW || ch_mode == MODE_NL)
3926 {
3927 EMSG(_("E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel"));
3928 return;
3929 }
3930
Bram Moolenaare9d6a292016-03-20 19:31:33 +01003931 id = ++channel->ch_last_msg_id;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003932 text = json_encode_nr_expr(id, &argvars[1],
Bram Moolenaarf1f07922016-08-26 17:58:53 +02003933 (ch_mode == MODE_JS ? JSON_JS : 0) | JSON_NL);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003934 if (text == NULL)
3935 return;
3936
3937 channel = send_common(argvars, text, id, eval, &opt,
3938 eval ? "ch_evalexpr" : "ch_sendexpr", &part_read);
3939 vim_free(text);
3940 if (channel != NULL && eval)
3941 {
3942 if (opt.jo_set & JO_TIMEOUT)
3943 timeout = opt.jo_timeout;
3944 else
3945 timeout = channel_get_timeout(channel, part_read);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003946 if (channel_read_json_block(channel, part_read, timeout, id, &listtv)
3947 == OK)
3948 {
3949 list_T *list = listtv->vval.v_list;
3950
3951 /* Move the item from the list and then change the type to
3952 * avoid the value being freed. */
3953 *rettv = list->lv_last->li_tv;
3954 list->lv_last->li_tv.v_type = VAR_NUMBER;
3955 free_tv(listtv);
3956 }
3957 }
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02003958 free_job_options(&opt);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003959}
3960
3961/*
3962 * common for "ch_evalraw()" and "ch_sendraw()"
3963 */
3964 void
3965ch_raw_common(typval_T *argvars, typval_T *rettv, int eval)
3966{
3967 char_u buf[NUMBUFLEN];
3968 char_u *text;
3969 channel_T *channel;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02003970 ch_part_T part_read;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003971 jobopt_T opt;
3972 int timeout;
3973
3974 /* return an empty string by default */
3975 rettv->v_type = VAR_STRING;
3976 rettv->vval.v_string = NULL;
3977
3978 text = get_tv_string_buf(&argvars[1], buf);
3979 channel = send_common(argvars, text, 0, eval, &opt,
3980 eval ? "ch_evalraw" : "ch_sendraw", &part_read);
3981 if (channel != NULL && eval)
3982 {
3983 if (opt.jo_set & JO_TIMEOUT)
3984 timeout = opt.jo_timeout;
3985 else
3986 timeout = channel_get_timeout(channel, part_read);
Bram Moolenaar620ca2d2017-12-09 19:13:13 +01003987 rettv->vval.v_string = channel_read_block(channel, part_read,
3988 timeout, TRUE);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003989 }
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02003990 free_job_options(&opt);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01003991}
3992
Bram Moolenaarf3360612017-10-01 16:21:31 +02003993# define KEEP_OPEN_TIME 20 /* msec */
3994
Bram Moolenaard04a0202016-01-26 23:30:18 +01003995# if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +01003996/*
3997 * Add open channels to the poll struct.
3998 * Return the adjusted struct index.
3999 * The type of "fds" is hidden to avoid problems with the function proto.
4000 */
4001 int
Bram Moolenaarf3360612017-10-01 16:21:31 +02004002channel_poll_setup(int nfd_in, void *fds_in, int *towait)
Bram Moolenaare0874f82016-01-24 20:36:41 +01004003{
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004004 int nfd = nfd_in;
4005 channel_T *channel;
4006 struct pollfd *fds = fds_in;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004007 ch_part_T part;
Bram Moolenaare0874f82016-01-24 20:36:41 +01004008
Bram Moolenaar77073442016-02-13 23:23:53 +01004009 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004010 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004011 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004012 {
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004013 chanpart_T *ch_part = &channel->ch_part[part];
4014
4015 if (ch_part->ch_fd != INVALID_FD)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004016 {
Bram Moolenaarf3360612017-10-01 16:21:31 +02004017 if (channel->ch_keep_open)
4018 {
4019 /* For unknown reason poll() returns immediately for a
4020 * keep-open channel. Instead of adding it to the fds add
4021 * a short timeout and check, like polling. */
4022 if (*towait < 0 || *towait > KEEP_OPEN_TIME)
4023 *towait = KEEP_OPEN_TIME;
4024 }
4025 else
4026 {
4027 ch_part->ch_poll_idx = nfd;
4028 fds[nfd].fd = ch_part->ch_fd;
4029 fds[nfd].events = POLLIN;
4030 nfd++;
4031 }
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004032 }
4033 else
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004034 channel->ch_part[part].ch_poll_idx = -1;
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004035 }
4036 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01004037
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004038 nfd = channel_fill_poll_write(nfd, fds);
4039
Bram Moolenaare0874f82016-01-24 20:36:41 +01004040 return nfd;
4041}
4042
4043/*
4044 * The type of "fds" is hidden to avoid problems with the function proto.
4045 */
4046 int
4047channel_poll_check(int ret_in, void *fds_in)
4048{
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004049 int ret = ret_in;
4050 channel_T *channel;
4051 struct pollfd *fds = fds_in;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004052 ch_part_T part;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004053 int idx;
4054 chanpart_T *in_part;
Bram Moolenaare0874f82016-01-24 20:36:41 +01004055
Bram Moolenaar77073442016-02-13 23:23:53 +01004056 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004057 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004058 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004059 {
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004060 idx = channel->ch_part[part].ch_poll_idx;
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004061
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004062 if (ret > 0 && idx != -1 && (fds[idx].revents & POLLIN))
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004063 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004064 channel_read(channel, part, "channel_poll_check");
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004065 --ret;
4066 }
Bram Moolenaarf3360612017-10-01 16:21:31 +02004067 else if (channel->ch_part[part].ch_fd != INVALID_FD
4068 && channel->ch_keep_open)
4069 {
4070 /* polling a keep-open channel */
4071 channel_read(channel, part, "channel_poll_check_keep_open");
4072 }
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004073 }
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004074
4075 in_part = &channel->ch_part[PART_IN];
4076 idx = in_part->ch_poll_idx;
4077 if (ret > 0 && idx != -1 && (fds[idx].revents & POLLOUT))
4078 {
Bram Moolenaar683b7962017-08-19 15:51:59 +02004079 channel_write_input(channel);
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004080 --ret;
4081 }
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004082 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01004083
4084 return ret;
4085}
Bram Moolenaard04a0202016-01-26 23:30:18 +01004086# endif /* UNIX && !HAVE_SELECT */
Bram Moolenaare0874f82016-01-24 20:36:41 +01004087
Bram Moolenaared5a78e2016-02-19 21:05:03 +01004088# if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO)
Bram Moolenaarf3360612017-10-01 16:21:31 +02004089
Bram Moolenaare0874f82016-01-24 20:36:41 +01004090/*
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004091 * The "fd_set" type is hidden to avoid problems with the function proto.
Bram Moolenaare0874f82016-01-24 20:36:41 +01004092 */
4093 int
Bram Moolenaarf3360612017-10-01 16:21:31 +02004094channel_select_setup(
4095 int maxfd_in,
4096 void *rfds_in,
4097 void *wfds_in,
4098 struct timeval *tv,
4099 struct timeval **tvp)
Bram Moolenaare0874f82016-01-24 20:36:41 +01004100{
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004101 int maxfd = maxfd_in;
4102 channel_T *channel;
4103 fd_set *rfds = rfds_in;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004104 fd_set *wfds = wfds_in;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004105 ch_part_T part;
Bram Moolenaare0874f82016-01-24 20:36:41 +01004106
Bram Moolenaar77073442016-02-13 23:23:53 +01004107 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004108 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004109 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004110 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004111 sock_T fd = channel->ch_part[part].ch_fd;
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004112
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004113 if (fd != INVALID_FD)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004114 {
Bram Moolenaarf3360612017-10-01 16:21:31 +02004115 if (channel->ch_keep_open)
4116 {
4117 /* For unknown reason select() returns immediately for a
4118 * keep-open channel. Instead of adding it to the rfds add
4119 * a short timeout and check, like polling. */
4120 if (*tvp == NULL || tv->tv_sec > 0
4121 || tv->tv_usec > KEEP_OPEN_TIME * 1000)
4122 {
4123 *tvp = tv;
4124 tv->tv_sec = 0;
4125 tv->tv_usec = KEEP_OPEN_TIME * 1000;
4126 }
4127 }
4128 else
4129 {
4130 FD_SET((int)fd, rfds);
4131 if (maxfd < (int)fd)
4132 maxfd = (int)fd;
4133 }
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004134 }
4135 }
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004136 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01004137
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004138 maxfd = channel_fill_wfds(maxfd, wfds);
4139
Bram Moolenaare0874f82016-01-24 20:36:41 +01004140 return maxfd;
4141}
4142
4143/*
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004144 * The "fd_set" type is hidden to avoid problems with the function proto.
Bram Moolenaare0874f82016-01-24 20:36:41 +01004145 */
4146 int
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004147channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
Bram Moolenaare0874f82016-01-24 20:36:41 +01004148{
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004149 int ret = ret_in;
4150 channel_T *channel;
4151 fd_set *rfds = rfds_in;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004152 fd_set *wfds = wfds_in;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004153 ch_part_T part;
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004154 chanpart_T *in_part;
Bram Moolenaare0874f82016-01-24 20:36:41 +01004155
Bram Moolenaar77073442016-02-13 23:23:53 +01004156 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004157 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004158 for (part = PART_SOCK; part < PART_IN; ++part)
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004159 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004160 sock_T fd = channel->ch_part[part].ch_fd;
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004161
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004162 if (ret > 0 && fd != INVALID_FD && FD_ISSET(fd, rfds))
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004163 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004164 channel_read(channel, part, "channel_select_check");
Bram Moolenaar3c518402017-09-08 20:47:00 +02004165 FD_CLR(fd, rfds);
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004166 --ret;
4167 }
Bram Moolenaarf3360612017-10-01 16:21:31 +02004168 else if (fd != INVALID_FD && channel->ch_keep_open)
4169 {
4170 /* polling a keep-open channel */
4171 channel_read(channel, part, "channel_select_check_keep_open");
4172 }
Bram Moolenaar7b3ca762016-02-14 19:13:43 +01004173 }
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004174
4175 in_part = &channel->ch_part[PART_IN];
4176 if (ret > 0 && in_part->ch_fd != INVALID_FD
4177 && FD_ISSET(in_part->ch_fd, wfds))
4178 {
Bram Moolenaar9af97782018-04-03 12:51:01 +02004179 /* Clear the flag first, ch_fd may change in channel_write_input(). */
Bram Moolenaar3c518402017-09-08 20:47:00 +02004180 FD_CLR(in_part->ch_fd, wfds);
Bram Moolenaar9af97782018-04-03 12:51:01 +02004181 channel_write_input(channel);
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004182 --ret;
4183 }
Bram Moolenaar16eb4f82016-02-14 23:02:34 +01004184 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01004185
4186 return ret;
4187}
Bram Moolenaared5a78e2016-02-19 21:05:03 +01004188# endif /* !WIN32 && HAVE_SELECT */
Bram Moolenaare0874f82016-01-24 20:36:41 +01004189
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01004190/*
Bram Moolenaard7ece102016-02-02 23:23:02 +01004191 * Execute queued up commands.
4192 * Invoked from the main loop when it's safe to execute received commands.
4193 * Return TRUE when something was done.
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01004194 */
Bram Moolenaard7ece102016-02-02 23:23:02 +01004195 int
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01004196channel_parse_messages(void)
4197{
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01004198 channel_T *channel = first_channel;
4199 int ret = FALSE;
4200 int r;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004201 ch_part_T part = PART_SOCK;
Bram Moolenaar833eb1d2016-11-24 17:22:50 +01004202#ifdef ELAPSED_FUNC
4203 ELAPSED_TYPE start_tv;
4204
4205 ELAPSED_INIT(start_tv);
4206#endif
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01004207
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +02004208 ++safe_to_invoke_callback;
4209
Bram Moolenaard0b65022016-03-06 21:50:33 +01004210 /* Only do this message when another message was given, otherwise we get
4211 * lots of them. */
4212 if (did_log_msg)
4213 {
4214 ch_log(NULL, "looking for messages on channels");
4215 did_log_msg = FALSE;
4216 }
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01004217 while (channel != NULL)
4218 {
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02004219 if (channel_can_close(channel))
Bram Moolenaarcf7ff702016-05-09 17:20:14 +02004220 {
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02004221 channel->ch_to_be_closed = (1U << PART_COUNT);
Bram Moolenaarcf7ff702016-05-09 17:20:14 +02004222 channel_close_now(channel);
4223 /* channel may have been freed, start over */
4224 channel = first_channel;
4225 continue;
4226 }
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +02004227 if (channel->ch_to_be_freed)
4228 {
4229 channel_free(channel);
4230 /* channel has been freed, start over */
4231 channel = first_channel;
4232 continue;
4233 }
Bram Moolenaar46c85432016-02-26 11:17:46 +01004234 if (channel->ch_refcount == 0 && !channel_still_useful(channel))
Bram Moolenaarc8dcbb12016-02-25 23:10:17 +01004235 {
4236 /* channel is no longer useful, free it */
4237 channel_free(channel);
4238 channel = first_channel;
4239 part = PART_SOCK;
4240 continue;
4241 }
Bram Moolenaar187db502016-02-27 14:44:26 +01004242 if (channel->ch_part[part].ch_fd != INVALID_FD
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004243 || channel_has_readahead(channel, part))
Bram Moolenaard7ece102016-02-02 23:23:02 +01004244 {
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004245 /* Increase the refcount, in case the handler causes the channel
4246 * to be unreferenced or closed. */
4247 ++channel->ch_refcount;
4248 r = may_invoke_callback(channel, part);
4249 if (r == OK)
4250 ret = TRUE;
Bram Moolenaar833eb1d2016-11-24 17:22:50 +01004251 if (channel_unref(channel) || (r == OK
4252#ifdef ELAPSED_FUNC
4253 /* Limit the time we loop here to 100 msec, otherwise
4254 * Vim becomes unresponsive when the callback takes
4255 * more than a bit of time. */
4256 && ELAPSED_FUNC(start_tv) < 100L
4257#endif
4258 ))
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004259 {
4260 /* channel was freed or something was done, start over */
4261 channel = first_channel;
4262 part = PART_SOCK;
4263 continue;
4264 }
Bram Moolenaard7ece102016-02-02 23:23:02 +01004265 }
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004266 if (part < PART_ERR)
4267 ++part;
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01004268 else
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004269 {
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01004270 channel = channel->ch_next;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004271 part = PART_SOCK;
4272 }
Bram Moolenaar3bece9f2016-02-15 20:39:46 +01004273 }
Bram Moolenaar187db502016-02-27 14:44:26 +01004274
Bram Moolenaar7f7c3322016-04-18 19:27:24 +02004275 if (channel_need_redraw)
Bram Moolenaar187db502016-02-27 14:44:26 +01004276 {
4277 channel_need_redraw = FALSE;
Bram Moolenaar02e177d2017-08-26 23:43:28 +02004278 redraw_after_callback(TRUE);
Bram Moolenaar187db502016-02-27 14:44:26 +01004279 }
4280
Bram Moolenaarfb6ffc72016-05-09 17:58:04 +02004281 --safe_to_invoke_callback;
4282
Bram Moolenaard7ece102016-02-02 23:23:02 +01004283 return ret;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01004284}
4285
Bram Moolenaarfbc4b4d2016-02-07 15:14:01 +01004286/*
Bram Moolenaar8a8199e2016-11-26 15:13:33 +01004287 * Return TRUE if any channel has readahead. That means we should not block on
4288 * waiting for input.
4289 */
4290 int
4291channel_any_readahead(void)
4292{
4293 channel_T *channel = first_channel;
4294 ch_part_T part = PART_SOCK;
4295
4296 while (channel != NULL)
4297 {
4298 if (channel_has_readahead(channel, part))
4299 return TRUE;
4300 if (part < PART_ERR)
4301 ++part;
4302 else
4303 {
4304 channel = channel->ch_next;
4305 part = PART_SOCK;
4306 }
4307 }
4308 return FALSE;
4309}
4310
4311/*
Bram Moolenaarfbc4b4d2016-02-07 15:14:01 +01004312 * Mark references to lists used in channels.
4313 */
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01004314 int
4315set_ref_in_channel(int copyID)
4316{
Bram Moolenaar77073442016-02-13 23:23:53 +01004317 int abort = FALSE;
4318 channel_T *channel;
Bram Moolenaarb8d49052016-05-01 14:22:16 +02004319 typval_T tv;
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01004320
Bram Moolenaar77073442016-02-13 23:23:53 +01004321 for (channel = first_channel; channel != NULL; channel = channel->ch_next)
Bram Moolenaarb8d49052016-05-01 14:22:16 +02004322 if (channel_still_useful(channel))
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01004323 {
Bram Moolenaarb8d49052016-05-01 14:22:16 +02004324 tv.v_type = VAR_CHANNEL;
4325 tv.vval.v_channel = channel;
4326 abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01004327 }
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01004328 return abort;
4329}
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01004330
4331/*
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004332 * Return the "part" to write to for "channel".
4333 */
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004334 ch_part_T
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004335channel_part_send(channel_T *channel)
4336{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004337 if (channel->CH_SOCK_FD == INVALID_FD)
4338 return PART_IN;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004339 return PART_SOCK;
4340}
4341
4342/*
4343 * Return the default "part" to read from for "channel".
4344 */
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004345 ch_part_T
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004346channel_part_read(channel_T *channel)
4347{
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004348 if (channel->CH_SOCK_FD == INVALID_FD)
4349 return PART_OUT;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004350 return PART_SOCK;
4351}
4352
4353/*
4354 * Return the mode of "channel"/"part"
Bram Moolenaar77073442016-02-13 23:23:53 +01004355 * If "channel" is invalid returns MODE_JSON.
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01004356 */
4357 ch_mode_T
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004358channel_get_mode(channel_T *channel, ch_part_T part)
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01004359{
Bram Moolenaar77073442016-02-13 23:23:53 +01004360 if (channel == NULL)
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01004361 return MODE_JSON;
Bram Moolenaar42d38a22016-02-20 18:18:59 +01004362 return channel->ch_part[part].ch_mode;
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01004363}
4364
Bram Moolenaar6f3a5442016-02-20 19:56:13 +01004365/*
4366 * Return the timeout of "channel"/"part"
4367 */
4368 int
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004369channel_get_timeout(channel_T *channel, ch_part_T part)
Bram Moolenaar6f3a5442016-02-20 19:56:13 +01004370{
4371 return channel->ch_part[part].ch_timeout;
4372}
4373
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004374 static int
4375handle_mode(typval_T *item, jobopt_T *opt, ch_mode_T *modep, int jo)
4376{
4377 char_u *val = get_tv_string(item);
4378
4379 opt->jo_set |= jo;
4380 if (STRCMP(val, "nl") == 0)
4381 *modep = MODE_NL;
4382 else if (STRCMP(val, "raw") == 0)
4383 *modep = MODE_RAW;
4384 else if (STRCMP(val, "js") == 0)
4385 *modep = MODE_JS;
4386 else if (STRCMP(val, "json") == 0)
4387 *modep = MODE_JSON;
4388 else
4389 {
4390 EMSG2(_(e_invarg2), val);
4391 return FAIL;
4392 }
4393 return OK;
4394}
4395
4396 static int
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004397handle_io(typval_T *item, ch_part_T part, jobopt_T *opt)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004398{
4399 char_u *val = get_tv_string(item);
4400
4401 opt->jo_set |= JO_OUT_IO << (part - PART_OUT);
4402 if (STRCMP(val, "null") == 0)
4403 opt->jo_io[part] = JIO_NULL;
4404 else if (STRCMP(val, "pipe") == 0)
4405 opt->jo_io[part] = JIO_PIPE;
4406 else if (STRCMP(val, "file") == 0)
4407 opt->jo_io[part] = JIO_FILE;
4408 else if (STRCMP(val, "buffer") == 0)
4409 opt->jo_io[part] = JIO_BUFFER;
4410 else if (STRCMP(val, "out") == 0 && part == PART_ERR)
4411 opt->jo_io[part] = JIO_OUT;
4412 else
4413 {
4414 EMSG2(_(e_invarg2), val);
4415 return FAIL;
4416 }
4417 return OK;
4418}
4419
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02004420/*
4421 * Clear a jobopt_T before using it.
4422 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004423 void
4424clear_job_options(jobopt_T *opt)
4425{
4426 vim_memset(opt, 0, sizeof(jobopt_T));
4427}
4428
4429/*
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02004430 * Free any members of a jobopt_T.
4431 */
4432 void
4433free_job_options(jobopt_T *opt)
4434{
4435 if (opt->jo_partial != NULL)
4436 partial_unref(opt->jo_partial);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004437 else if (opt->jo_callback != NULL)
4438 func_unref(opt->jo_callback);
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02004439 if (opt->jo_out_partial != NULL)
4440 partial_unref(opt->jo_out_partial);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004441 else if (opt->jo_out_cb != NULL)
4442 func_unref(opt->jo_out_cb);
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02004443 if (opt->jo_err_partial != NULL)
4444 partial_unref(opt->jo_err_partial);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004445 else if (opt->jo_err_cb != NULL)
4446 func_unref(opt->jo_err_cb);
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02004447 if (opt->jo_close_partial != NULL)
4448 partial_unref(opt->jo_close_partial);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004449 else if (opt->jo_close_cb != NULL)
4450 func_unref(opt->jo_close_cb);
Bram Moolenaaref3abc62016-05-29 16:44:26 +02004451 if (opt->jo_exit_partial != NULL)
4452 partial_unref(opt->jo_exit_partial);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02004453 else if (opt->jo_exit_cb != NULL)
4454 func_unref(opt->jo_exit_cb);
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004455 if (opt->jo_env != NULL)
4456 dict_unref(opt->jo_env);
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02004457}
4458
4459/*
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004460 * Get the PART_ number from the first character of an option name.
4461 */
4462 static int
4463part_from_char(int c)
4464{
4465 return c == 'i' ? PART_IN : c == 'o' ? PART_OUT: PART_ERR;
4466}
4467
4468/*
4469 * Get the option entries from the dict in "tv", parse them and put the result
4470 * in "opt".
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004471 * Only accept JO_ options in "supported" and JO2_ options in "supported2".
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004472 * If an option value is invalid return FAIL.
4473 */
4474 int
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004475get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004476{
4477 typval_T *item;
4478 char_u *val;
4479 dict_T *dict;
4480 int todo;
4481 hashitem_T *hi;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004482 ch_part_T part;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004483
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004484 if (tv->v_type == VAR_UNKNOWN)
4485 return OK;
4486 if (tv->v_type != VAR_DICT)
4487 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004488 EMSG(_(e_dictreq));
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004489 return FAIL;
4490 }
4491 dict = tv->vval.v_dict;
4492 if (dict == NULL)
4493 return OK;
4494
4495 todo = (int)dict->dv_hashtab.ht_used;
4496 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
4497 if (!HASHITEM_EMPTY(hi))
4498 {
4499 item = &dict_lookup(hi)->di_tv;
4500
4501 if (STRCMP(hi->hi_key, "mode") == 0)
4502 {
4503 if (!(supported & JO_MODE))
4504 break;
4505 if (handle_mode(item, opt, &opt->jo_mode, JO_MODE) == FAIL)
4506 return FAIL;
4507 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004508 else if (STRCMP(hi->hi_key, "in_mode") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004509 {
4510 if (!(supported & JO_IN_MODE))
4511 break;
4512 if (handle_mode(item, opt, &opt->jo_in_mode, JO_IN_MODE)
4513 == FAIL)
4514 return FAIL;
4515 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004516 else if (STRCMP(hi->hi_key, "out_mode") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004517 {
4518 if (!(supported & JO_OUT_MODE))
4519 break;
4520 if (handle_mode(item, opt, &opt->jo_out_mode, JO_OUT_MODE)
4521 == FAIL)
4522 return FAIL;
4523 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004524 else if (STRCMP(hi->hi_key, "err_mode") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004525 {
4526 if (!(supported & JO_ERR_MODE))
4527 break;
4528 if (handle_mode(item, opt, &opt->jo_err_mode, JO_ERR_MODE)
4529 == FAIL)
4530 return FAIL;
4531 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004532 else if (STRCMP(hi->hi_key, "in_io") == 0
4533 || STRCMP(hi->hi_key, "out_io") == 0
4534 || STRCMP(hi->hi_key, "err_io") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004535 {
4536 if (!(supported & JO_OUT_IO))
4537 break;
4538 if (handle_io(item, part_from_char(*hi->hi_key), opt) == FAIL)
4539 return FAIL;
4540 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004541 else if (STRCMP(hi->hi_key, "in_name") == 0
4542 || STRCMP(hi->hi_key, "out_name") == 0
4543 || STRCMP(hi->hi_key, "err_name") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004544 {
4545 part = part_from_char(*hi->hi_key);
4546
4547 if (!(supported & JO_OUT_IO))
4548 break;
4549 opt->jo_set |= JO_OUT_NAME << (part - PART_OUT);
4550 opt->jo_io_name[part] =
4551 get_tv_string_buf_chk(item, opt->jo_io_name_buf[part]);
4552 }
Bram Moolenaar5a1feb82017-07-22 18:04:08 +02004553 else if (STRCMP(hi->hi_key, "pty") == 0)
4554 {
4555 if (!(supported & JO_MODE))
4556 break;
4557 opt->jo_pty = get_tv_number(item);
4558 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004559 else if (STRCMP(hi->hi_key, "in_buf") == 0
4560 || STRCMP(hi->hi_key, "out_buf") == 0
4561 || STRCMP(hi->hi_key, "err_buf") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004562 {
4563 part = part_from_char(*hi->hi_key);
4564
4565 if (!(supported & JO_OUT_IO))
4566 break;
4567 opt->jo_set |= JO_OUT_BUF << (part - PART_OUT);
4568 opt->jo_io_buf[part] = get_tv_number(item);
4569 if (opt->jo_io_buf[part] <= 0)
4570 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004571 EMSG3(_(e_invargNval), hi->hi_key, get_tv_string(item));
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004572 return FAIL;
4573 }
4574 if (buflist_findnr(opt->jo_io_buf[part]) == NULL)
4575 {
4576 EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[part]);
4577 return FAIL;
4578 }
4579 }
Bram Moolenaar9f5842e2016-05-29 16:17:08 +02004580 else if (STRCMP(hi->hi_key, "out_modifiable") == 0
4581 || STRCMP(hi->hi_key, "err_modifiable") == 0)
4582 {
4583 part = part_from_char(*hi->hi_key);
4584
4585 if (!(supported & JO_OUT_IO))
4586 break;
4587 opt->jo_set |= JO_OUT_MODIFIABLE << (part - PART_OUT);
4588 opt->jo_modifiable[part] = get_tv_number(item);
4589 }
Bram Moolenaar169ebb02016-09-07 23:32:23 +02004590 else if (STRCMP(hi->hi_key, "out_msg") == 0
4591 || STRCMP(hi->hi_key, "err_msg") == 0)
4592 {
4593 part = part_from_char(*hi->hi_key);
4594
4595 if (!(supported & JO_OUT_IO))
4596 break;
4597 opt->jo_set2 |= JO2_OUT_MSG << (part - PART_OUT);
4598 opt->jo_message[part] = get_tv_number(item);
4599 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004600 else if (STRCMP(hi->hi_key, "in_top") == 0
4601 || STRCMP(hi->hi_key, "in_bot") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004602 {
4603 linenr_T *lp;
4604
4605 if (!(supported & JO_OUT_IO))
4606 break;
4607 if (hi->hi_key[3] == 't')
4608 {
4609 lp = &opt->jo_in_top;
4610 opt->jo_set |= JO_IN_TOP;
4611 }
4612 else
4613 {
4614 lp = &opt->jo_in_bot;
4615 opt->jo_set |= JO_IN_BOT;
4616 }
4617 *lp = get_tv_number(item);
4618 if (*lp < 0)
4619 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004620 EMSG3(_(e_invargNval), hi->hi_key, get_tv_string(item));
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004621 return FAIL;
4622 }
4623 }
4624 else if (STRCMP(hi->hi_key, "channel") == 0)
4625 {
4626 if (!(supported & JO_OUT_IO))
4627 break;
4628 opt->jo_set |= JO_CHANNEL;
4629 if (item->v_type != VAR_CHANNEL)
4630 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004631 EMSG2(_(e_invargval), "channel");
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004632 return FAIL;
4633 }
4634 opt->jo_channel = item->vval.v_channel;
4635 }
4636 else if (STRCMP(hi->hi_key, "callback") == 0)
4637 {
4638 if (!(supported & JO_CALLBACK))
4639 break;
4640 opt->jo_set |= JO_CALLBACK;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004641 opt->jo_callback = get_callback(item, &opt->jo_partial);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004642 if (opt->jo_callback == NULL)
4643 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004644 EMSG2(_(e_invargval), "callback");
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004645 return FAIL;
4646 }
4647 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004648 else if (STRCMP(hi->hi_key, "out_cb") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004649 {
4650 if (!(supported & JO_OUT_CALLBACK))
4651 break;
4652 opt->jo_set |= JO_OUT_CALLBACK;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004653 opt->jo_out_cb = get_callback(item, &opt->jo_out_partial);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004654 if (opt->jo_out_cb == NULL)
4655 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004656 EMSG2(_(e_invargval), "out_cb");
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004657 return FAIL;
4658 }
4659 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004660 else if (STRCMP(hi->hi_key, "err_cb") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004661 {
4662 if (!(supported & JO_ERR_CALLBACK))
4663 break;
4664 opt->jo_set |= JO_ERR_CALLBACK;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004665 opt->jo_err_cb = get_callback(item, &opt->jo_err_partial);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004666 if (opt->jo_err_cb == NULL)
4667 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004668 EMSG2(_(e_invargval), "err_cb");
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004669 return FAIL;
4670 }
4671 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004672 else if (STRCMP(hi->hi_key, "close_cb") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004673 {
4674 if (!(supported & JO_CLOSE_CALLBACK))
4675 break;
4676 opt->jo_set |= JO_CLOSE_CALLBACK;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01004677 opt->jo_close_cb = get_callback(item, &opt->jo_close_partial);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004678 if (opt->jo_close_cb == NULL)
4679 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004680 EMSG2(_(e_invargval), "close_cb");
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004681 return FAIL;
4682 }
4683 }
Bram Moolenaar958dc692016-12-01 15:34:12 +01004684 else if (STRCMP(hi->hi_key, "drop") == 0)
4685 {
4686 int never = FALSE;
4687 val = get_tv_string(item);
4688
4689 if (STRCMP(val, "never") == 0)
4690 never = TRUE;
4691 else if (STRCMP(val, "auto") != 0)
4692 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004693 EMSG3(_(e_invargNval), "drop", val);
Bram Moolenaar958dc692016-12-01 15:34:12 +01004694 return FAIL;
4695 }
4696 opt->jo_drop_never = never;
4697 }
Bram Moolenaaref3abc62016-05-29 16:44:26 +02004698 else if (STRCMP(hi->hi_key, "exit_cb") == 0)
4699 {
4700 if (!(supported & JO_EXIT_CB))
4701 break;
4702 opt->jo_set |= JO_EXIT_CB;
4703 opt->jo_exit_cb = get_callback(item, &opt->jo_exit_partial);
4704 if (opt->jo_exit_cb == NULL)
4705 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004706 EMSG2(_(e_invargval), "exit_cb");
Bram Moolenaaref3abc62016-05-29 16:44:26 +02004707 return FAIL;
4708 }
4709 }
Bram Moolenaar8456ea82017-08-05 15:02:05 +02004710#ifdef FEAT_TERMINAL
Bram Moolenaar78712a72017-08-05 14:50:12 +02004711 else if (STRCMP(hi->hi_key, "term_name") == 0)
4712 {
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004713 if (!(supported2 & JO2_TERM_NAME))
Bram Moolenaar78712a72017-08-05 14:50:12 +02004714 break;
4715 opt->jo_set2 |= JO2_TERM_NAME;
4716 opt->jo_term_name = get_tv_string_chk(item);
4717 if (opt->jo_term_name == NULL)
4718 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004719 EMSG2(_(e_invargval), "term_name");
Bram Moolenaar78712a72017-08-05 14:50:12 +02004720 return FAIL;
4721 }
4722 }
Bram Moolenaardd693ce2017-08-10 23:15:19 +02004723 else if (STRCMP(hi->hi_key, "term_finish") == 0)
4724 {
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004725 if (!(supported2 & JO2_TERM_FINISH))
Bram Moolenaardd693ce2017-08-10 23:15:19 +02004726 break;
4727 val = get_tv_string(item);
4728 if (STRCMP(val, "open") != 0 && STRCMP(val, "close") != 0)
4729 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004730 EMSG3(_(e_invargNval), "term_finish", val);
Bram Moolenaardd693ce2017-08-10 23:15:19 +02004731 return FAIL;
4732 }
4733 opt->jo_set2 |= JO2_TERM_FINISH;
4734 opt->jo_term_finish = *val;
4735 }
Bram Moolenaar37c45832017-08-12 16:01:04 +02004736 else if (STRCMP(hi->hi_key, "term_opencmd") == 0)
4737 {
4738 char_u *p;
4739
4740 if (!(supported2 & JO2_TERM_OPENCMD))
4741 break;
4742 opt->jo_set2 |= JO2_TERM_OPENCMD;
4743 p = opt->jo_term_opencmd = get_tv_string_chk(item);
4744 if (p != NULL)
4745 {
4746 /* Must have %d and no other %. */
4747 p = vim_strchr(p, '%');
4748 if (p != NULL && (p[1] != 'd'
4749 || vim_strchr(p + 2, '%') != NULL))
4750 p = NULL;
4751 }
4752 if (p == NULL)
4753 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004754 EMSG2(_(e_invargval), "term_opencmd");
Bram Moolenaar37c45832017-08-12 16:01:04 +02004755 return FAIL;
4756 }
4757 }
Bram Moolenaar3346cc42017-09-02 14:54:21 +02004758 else if (STRCMP(hi->hi_key, "eof_chars") == 0)
4759 {
Bram Moolenaar3346cc42017-09-02 14:54:21 +02004760 char_u *p;
4761
4762 if (!(supported2 & JO2_EOF_CHARS))
4763 break;
4764 opt->jo_set2 |= JO2_EOF_CHARS;
4765 p = opt->jo_eof_chars = get_tv_string_chk(item);
4766 if (p == NULL)
4767 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004768 EMSG2(_(e_invargval), "eof_chars");
Bram Moolenaar3346cc42017-09-02 14:54:21 +02004769 return FAIL;
4770 }
Bram Moolenaar3346cc42017-09-02 14:54:21 +02004771 }
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004772 else if (STRCMP(hi->hi_key, "term_rows") == 0)
4773 {
4774 if (!(supported2 & JO2_TERM_ROWS))
4775 break;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004776 opt->jo_set2 |= JO2_TERM_ROWS;
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004777 opt->jo_term_rows = get_tv_number(item);
4778 }
4779 else if (STRCMP(hi->hi_key, "term_cols") == 0)
4780 {
4781 if (!(supported2 & JO2_TERM_COLS))
4782 break;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004783 opt->jo_set2 |= JO2_TERM_COLS;
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004784 opt->jo_term_cols = get_tv_number(item);
4785 }
4786 else if (STRCMP(hi->hi_key, "vertical") == 0)
4787 {
4788 if (!(supported2 & JO2_VERTICAL))
4789 break;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004790 opt->jo_set2 |= JO2_VERTICAL;
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004791 opt->jo_vertical = get_tv_number(item);
4792 }
Bram Moolenaarda43b612017-08-11 22:27:50 +02004793 else if (STRCMP(hi->hi_key, "curwin") == 0)
4794 {
4795 if (!(supported2 & JO2_CURWIN))
4796 break;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004797 opt->jo_set2 |= JO2_CURWIN;
Bram Moolenaarda43b612017-08-11 22:27:50 +02004798 opt->jo_curwin = get_tv_number(item);
4799 }
Bram Moolenaar8cad9302017-08-12 14:32:32 +02004800 else if (STRCMP(hi->hi_key, "hidden") == 0)
4801 {
4802 if (!(supported2 & JO2_HIDDEN))
4803 break;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004804 opt->jo_set2 |= JO2_HIDDEN;
Bram Moolenaar8cad9302017-08-12 14:32:32 +02004805 opt->jo_hidden = get_tv_number(item);
4806 }
Bram Moolenaar4d8bac82018-03-09 21:33:34 +01004807 else if (STRCMP(hi->hi_key, "norestore") == 0)
4808 {
4809 if (!(supported2 & JO2_NORESTORE))
4810 break;
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004811 opt->jo_set2 |= JO2_NORESTORE;
Bram Moolenaar4d8bac82018-03-09 21:33:34 +01004812 opt->jo_term_norestore = get_tv_number(item);
4813 }
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004814 else if (STRCMP(hi->hi_key, "term_kill") == 0)
4815 {
4816 if (!(supported2 & JO2_TERM_KILL))
4817 break;
4818 opt->jo_set2 |= JO2_TERM_KILL;
4819 opt->jo_term_kill = get_tv_string_chk(item);
4820 }
Bram Moolenaarf59c6e82018-04-10 15:59:11 +02004821# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
4822 else if (STRCMP(hi->hi_key, "ansi_colors") == 0)
4823 {
4824 int n = 0;
4825 listitem_T *li;
4826 long_u rgb[16];
4827
4828 if (!(supported2 & JO2_ANSI_COLORS))
4829 break;
4830
4831 if (item == NULL || item->v_type != VAR_LIST
4832 || item->vval.v_list == NULL)
4833 {
4834 EMSG2(_(e_invargval), "ansi_colors");
4835 return FAIL;
4836 }
4837
4838 li = item->vval.v_list->lv_first;
4839 for (; li != NULL && n < 16; li = li->li_next, n++)
4840 {
4841 char_u *color_name;
4842 guicolor_T guicolor;
4843
4844 color_name = get_tv_string_chk(&li->li_tv);
4845 if (color_name == NULL)
4846 return FAIL;
4847
4848 guicolor = GUI_GET_COLOR(color_name);
4849 if (guicolor == INVALCOLOR)
4850 return FAIL;
4851
4852 rgb[n] = GUI_MCH_GET_RGB(guicolor);
4853 }
4854
4855 if (n != 16 || li != NULL)
4856 {
4857 EMSG2(_(e_invargval), "ansi_colors");
4858 return FAIL;
4859 }
4860
4861 opt->jo_set2 |= JO2_ANSI_COLORS;
4862 memcpy(opt->jo_ansi_colors, rgb, sizeof(rgb));
4863 }
4864# endif
Bram Moolenaar8456ea82017-08-05 15:02:05 +02004865#endif
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004866 else if (STRCMP(hi->hi_key, "env") == 0)
4867 {
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004868 if (!(supported2 & JO2_ENV))
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004869 break;
Bram Moolenaar22efba42018-04-07 13:22:21 +02004870 if (item->v_type != VAR_DICT)
4871 {
4872 EMSG2(_(e_invargval), "env");
4873 return FAIL;
4874 }
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004875 opt->jo_set2 |= JO2_ENV;
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004876 opt->jo_env = item->vval.v_dict;
Bram Moolenaar22efba42018-04-07 13:22:21 +02004877 if (opt->jo_env != NULL)
4878 ++opt->jo_env->dv_refcount;
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004879 }
4880 else if (STRCMP(hi->hi_key, "cwd") == 0)
4881 {
Bram Moolenaar08d384f2017-08-11 21:51:23 +02004882 if (!(supported2 & JO2_CWD))
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004883 break;
4884 opt->jo_cwd = get_tv_string_buf_chk(item, opt->jo_cwd_buf);
4885 if (opt->jo_cwd == NULL || !mch_isdir(opt->jo_cwd))
4886 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004887 EMSG2(_(e_invargval), "cwd");
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004888 return FAIL;
4889 }
Bram Moolenaar25cdd9c2018-03-10 20:28:12 +01004890 opt->jo_set2 |= JO2_CWD;
Bram Moolenaar05aafed2017-08-11 19:12:11 +02004891 }
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004892 else if (STRCMP(hi->hi_key, "waittime") == 0)
4893 {
4894 if (!(supported & JO_WAITTIME))
4895 break;
4896 opt->jo_set |= JO_WAITTIME;
4897 opt->jo_waittime = get_tv_number(item);
4898 }
4899 else if (STRCMP(hi->hi_key, "timeout") == 0)
4900 {
4901 if (!(supported & JO_TIMEOUT))
4902 break;
4903 opt->jo_set |= JO_TIMEOUT;
4904 opt->jo_timeout = get_tv_number(item);
4905 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004906 else if (STRCMP(hi->hi_key, "out_timeout") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004907 {
4908 if (!(supported & JO_OUT_TIMEOUT))
4909 break;
4910 opt->jo_set |= JO_OUT_TIMEOUT;
4911 opt->jo_out_timeout = get_tv_number(item);
4912 }
Bram Moolenaard6c2f052016-03-14 23:22:59 +01004913 else if (STRCMP(hi->hi_key, "err_timeout") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004914 {
4915 if (!(supported & JO_ERR_TIMEOUT))
4916 break;
4917 opt->jo_set |= JO_ERR_TIMEOUT;
4918 opt->jo_err_timeout = get_tv_number(item);
4919 }
4920 else if (STRCMP(hi->hi_key, "part") == 0)
4921 {
4922 if (!(supported & JO_PART))
4923 break;
4924 opt->jo_set |= JO_PART;
4925 val = get_tv_string(item);
4926 if (STRCMP(val, "err") == 0)
4927 opt->jo_part = PART_ERR;
Bram Moolenaar7ef38102016-09-26 22:36:58 +02004928 else if (STRCMP(val, "out") == 0)
4929 opt->jo_part = PART_OUT;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004930 else
4931 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004932 EMSG3(_(e_invargNval), "part", val);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004933 return FAIL;
4934 }
4935 }
4936 else if (STRCMP(hi->hi_key, "id") == 0)
4937 {
4938 if (!(supported & JO_ID))
4939 break;
4940 opt->jo_set |= JO_ID;
4941 opt->jo_id = get_tv_number(item);
4942 }
4943 else if (STRCMP(hi->hi_key, "stoponexit") == 0)
4944 {
4945 if (!(supported & JO_STOPONEXIT))
4946 break;
4947 opt->jo_set |= JO_STOPONEXIT;
4948 opt->jo_stoponexit = get_tv_string_buf_chk(item,
4949 opt->jo_soe_buf);
4950 if (opt->jo_stoponexit == NULL)
4951 {
Bram Moolenaarb3292fa2018-02-13 15:17:58 +01004952 EMSG2(_(e_invargval), "stoponexit");
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004953 return FAIL;
4954 }
4955 }
Bram Moolenaar8b877ac2016-03-28 19:16:20 +02004956 else if (STRCMP(hi->hi_key, "block_write") == 0)
4957 {
4958 if (!(supported & JO_BLOCK_WRITE))
4959 break;
4960 opt->jo_set |= JO_BLOCK_WRITE;
4961 opt->jo_block_write = get_tv_number(item);
4962 }
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004963 else
4964 break;
4965 --todo;
4966 }
4967 if (todo > 0)
4968 {
4969 EMSG2(_(e_invarg2), hi->hi_key);
4970 return FAIL;
4971 }
4972
4973 return OK;
4974}
4975
4976/*
4977 * Get the channel from the argument.
4978 * Returns NULL if the handle is invalid.
Bram Moolenaar437905c2016-04-26 19:01:05 +02004979 * When "check_open" is TRUE check that the channel can be used.
4980 * When "reading" is TRUE "check_open" considers typeahead useful.
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004981 * "part" is used to check typeahead, when PART_COUNT use the default part.
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004982 */
4983 channel_T *
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02004984get_channel_arg(typval_T *tv, int check_open, int reading, ch_part_T part)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004985{
Bram Moolenaar437905c2016-04-26 19:01:05 +02004986 channel_T *channel = NULL;
4987 int has_readahead = FALSE;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01004988
4989 if (tv->v_type == VAR_JOB)
4990 {
4991 if (tv->vval.v_job != NULL)
4992 channel = tv->vval.v_job->jv_channel;
4993 }
4994 else if (tv->v_type == VAR_CHANNEL)
4995 {
4996 channel = tv->vval.v_channel;
4997 }
4998 else
4999 {
5000 EMSG2(_(e_invarg2), get_tv_string(tv));
5001 return NULL;
5002 }
Bram Moolenaar437905c2016-04-26 19:01:05 +02005003 if (channel != NULL && reading)
5004 has_readahead = channel_has_readahead(channel,
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02005005 part != PART_COUNT ? part : channel_part_read(channel));
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005006
Bram Moolenaar437905c2016-04-26 19:01:05 +02005007 if (check_open && (channel == NULL || (!channel_is_open(channel)
5008 && !(reading && has_readahead))))
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005009 {
5010 EMSG(_("E906: not an open channel"));
5011 return NULL;
5012 }
5013 return channel;
5014}
5015
5016static job_T *first_job = NULL;
5017
5018 static void
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005019job_free_contents(job_T *job)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005020{
Bram Moolenaare1fc5152018-04-21 19:49:08 +02005021 int i;
5022
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005023 ch_log(job->jv_channel, "Freeing job");
5024 if (job->jv_channel != NULL)
5025 {
5026 /* The link from the channel to the job doesn't count as a reference,
5027 * thus don't decrement the refcount of the job. The reference from
Bram Moolenaaraad30bb2016-06-26 17:31:03 +02005028 * the job to the channel does count the reference, decrement it and
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005029 * NULL the reference. We don't set ch_job_killed, unreferencing the
5030 * job doesn't mean it stops running. */
5031 job->jv_channel->ch_job = NULL;
5032 channel_unref(job->jv_channel);
5033 }
5034 mch_clear_job(job);
5035
Bram Moolenaar2dc9d262017-09-08 14:39:30 +02005036 vim_free(job->jv_tty_in);
5037 vim_free(job->jv_tty_out);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005038 vim_free(job->jv_stoponexit);
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02005039 free_callback(job->jv_exit_cb, job->jv_exit_partial);
Bram Moolenaar20608922018-04-21 22:30:08 +02005040 if (job->jv_argv != NULL)
Bram Moolenaare1fc5152018-04-21 19:49:08 +02005041 {
Bram Moolenaar20608922018-04-21 22:30:08 +02005042 for (i = 0; job->jv_argv[i] != NULL; i++)
5043 vim_free(job->jv_argv[i]);
5044 vim_free(job->jv_argv);
Bram Moolenaare1fc5152018-04-21 19:49:08 +02005045 }
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005046}
5047
5048 static void
5049job_free_job(job_T *job)
5050{
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005051 if (job->jv_next != NULL)
5052 job->jv_next->jv_prev = job->jv_prev;
5053 if (job->jv_prev == NULL)
5054 first_job = job->jv_next;
5055 else
5056 job->jv_prev->jv_next = job->jv_next;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005057 vim_free(job);
5058}
5059
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005060 static void
5061job_free(job_T *job)
5062{
5063 if (!in_free_unref_items)
5064 {
5065 job_free_contents(job);
5066 job_free_job(job);
5067 }
5068}
5069
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005070#if defined(EXITFREE) || defined(PROTO)
5071 void
5072job_free_all(void)
5073{
5074 while (first_job != NULL)
5075 job_free(first_job);
5076}
5077#endif
5078
5079/*
5080 * Return TRUE if we need to check if the process of "job" has ended.
5081 */
5082 static int
5083job_need_end_check(job_T *job)
5084{
5085 return job->jv_status == JOB_STARTED
5086 && (job->jv_stoponexit != NULL || job->jv_exit_cb != NULL);
5087}
5088
5089/*
5090 * Return TRUE if the channel of "job" is still useful.
5091 */
5092 static int
5093job_channel_still_useful(job_T *job)
5094{
5095 return job->jv_channel != NULL && channel_still_useful(job->jv_channel);
5096}
5097
5098/*
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02005099 * Return TRUE if the channel of "job" is closeable.
5100 */
5101 static int
5102job_channel_can_close(job_T *job)
5103{
5104 return job->jv_channel != NULL && channel_can_close(job->jv_channel);
5105}
5106
5107/*
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005108 * Return TRUE if the job should not be freed yet. Do not free the job when
5109 * it has not ended yet and there is a "stoponexit" flag, an exit callback
5110 * or when the associated channel will do something with the job output.
5111 */
5112 static int
5113job_still_useful(job_T *job)
5114{
5115 return job_need_end_check(job) || job_channel_still_useful(job);
5116}
5117
Bram Moolenaardcaa6132017-08-13 17:13:09 +02005118#if !defined(USE_ARGV) || defined(PROTO)
5119/*
5120 * Escape one argument for an external command.
5121 * Returns the escaped string in allocated memory. NULL when out of memory.
5122 */
5123 static char_u *
5124win32_escape_arg(char_u *arg)
5125{
5126 int slen, dlen;
5127 int escaping = 0;
5128 int i;
5129 char_u *s, *d;
5130 char_u *escaped_arg;
5131 int has_spaces = FALSE;
5132
5133 /* First count the number of extra bytes required. */
Bram Moolenaare85928a2017-08-27 13:10:10 +02005134 slen = (int)STRLEN(arg);
Bram Moolenaardcaa6132017-08-13 17:13:09 +02005135 dlen = slen;
5136 for (s = arg; *s != NUL; MB_PTR_ADV(s))
5137 {
5138 if (*s == '"' || *s == '\\')
5139 ++dlen;
5140 if (*s == ' ' || *s == '\t')
5141 has_spaces = TRUE;
5142 }
5143
5144 if (has_spaces)
5145 dlen += 2;
5146
5147 if (dlen == slen)
5148 return vim_strsave(arg);
5149
5150 /* Allocate memory for the result and fill it. */
5151 escaped_arg = alloc(dlen + 1);
5152 if (escaped_arg == NULL)
5153 return NULL;
5154 memset(escaped_arg, 0, dlen+1);
5155
5156 d = escaped_arg;
5157
5158 if (has_spaces)
5159 *d++ = '"';
5160
5161 for (s = arg; *s != NUL;)
5162 {
5163 switch (*s)
5164 {
5165 case '"':
5166 for (i = 0; i < escaping; i++)
5167 *d++ = '\\';
5168 escaping = 0;
5169 *d++ = '\\';
5170 *d++ = *s++;
5171 break;
5172 case '\\':
5173 escaping++;
5174 *d++ = *s++;
5175 break;
5176 default:
5177 escaping = 0;
5178 MB_COPY_CHAR(s, d);
5179 break;
5180 }
5181 }
5182
5183 /* add terminating quote and finish with a NUL */
5184 if (has_spaces)
5185 {
5186 for (i = 0; i < escaping; i++)
5187 *d++ = '\\';
5188 *d++ = '"';
5189 }
5190 *d = NUL;
5191
5192 return escaped_arg;
5193}
5194
5195/*
5196 * Build a command line from a list, taking care of escaping.
5197 * The result is put in gap->ga_data.
5198 * Returns FAIL when out of memory.
5199 */
5200 int
5201win32_build_cmd(list_T *l, garray_T *gap)
5202{
5203 listitem_T *li;
5204 char_u *s;
5205
5206 for (li = l->lv_first; li != NULL; li = li->li_next)
5207 {
5208 s = get_tv_string_chk(&li->li_tv);
5209 if (s == NULL)
5210 return FAIL;
5211 s = win32_escape_arg(s);
5212 if (s == NULL)
5213 return FAIL;
5214 ga_concat(gap, s);
5215 vim_free(s);
5216 if (li->li_next != NULL)
5217 ga_append(gap, ' ');
5218 }
5219 return OK;
5220}
5221#endif
5222
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005223/*
5224 * NOTE: Must call job_cleanup() only once right after the status of "job"
5225 * changed to JOB_ENDED (i.e. after job_status() returned "dead" first or
5226 * mch_detect_ended_job() returned non-NULL).
5227 */
Bram Moolenaar8f84c3a2017-07-22 16:14:44 +02005228 void
Bram Moolenaar97792de2016-10-15 18:36:49 +02005229job_cleanup(job_T *job)
5230{
5231 if (job->jv_status != JOB_ENDED)
5232 return;
5233
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005234 /* Ready to cleanup the job. */
5235 job->jv_status = JOB_FINISHED;
5236
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02005237 /* When only channel-in is kept open, close explicitly. */
5238 if (job->jv_channel != NULL)
5239 ch_close_part(job->jv_channel, PART_IN);
5240
Bram Moolenaar97792de2016-10-15 18:36:49 +02005241 if (job->jv_exit_cb != NULL)
5242 {
5243 typval_T argv[3];
5244 typval_T rettv;
5245 int dummy;
5246
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005247 /* Invoke the exit callback. Make sure the refcount is > 0. */
Bram Moolenaar3c3a80d2017-08-03 17:06:45 +02005248 ch_log(job->jv_channel, "Invoking exit callback %s", job->jv_exit_cb);
Bram Moolenaar97792de2016-10-15 18:36:49 +02005249 ++job->jv_refcount;
5250 argv[0].v_type = VAR_JOB;
5251 argv[0].vval.v_job = job;
5252 argv[1].v_type = VAR_NUMBER;
5253 argv[1].vval.v_number = job->jv_exitval;
5254 call_func(job->jv_exit_cb, (int)STRLEN(job->jv_exit_cb),
5255 &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE,
5256 job->jv_exit_partial, NULL);
5257 clear_tv(&rettv);
5258 --job->jv_refcount;
5259 channel_need_redraw = TRUE;
5260 }
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005261
5262 /* Do not free the job in case the close callback of the associated channel
5263 * isn't invoked yet and may get information by job_info(). */
5264 if (job->jv_refcount == 0 && !job_channel_still_useful(job))
Bram Moolenaar97792de2016-10-15 18:36:49 +02005265 {
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005266 /* The job was already unreferenced and the associated channel was
5267 * detached, now that it ended it can be freed. Careful: caller must
5268 * not use "job" after this! */
Bram Moolenaar97792de2016-10-15 18:36:49 +02005269 job_free(job);
5270 }
5271}
5272
Bram Moolenaarb8d49052016-05-01 14:22:16 +02005273/*
5274 * Mark references in jobs that are still useful.
5275 */
5276 int
5277set_ref_in_job(int copyID)
5278{
5279 int abort = FALSE;
5280 job_T *job;
5281 typval_T tv;
5282
5283 for (job = first_job; job != NULL; job = job->jv_next)
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005284 if (job_still_useful(job))
Bram Moolenaarb8d49052016-05-01 14:22:16 +02005285 {
5286 tv.v_type = VAR_JOB;
5287 tv.vval.v_job = job;
5288 abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
5289 }
5290 return abort;
5291}
5292
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005293/*
5294 * Dereference "job". Note that after this "job" may have been freed.
5295 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005296 void
5297job_unref(job_T *job)
5298{
5299 if (job != NULL && --job->jv_refcount <= 0)
5300 {
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005301 /* Do not free the job if there is a channel where the close callback
5302 * may get the job info. */
5303 if (!job_channel_still_useful(job))
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005304 {
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005305 /* Do not free the job when it has not ended yet and there is a
5306 * "stoponexit" flag or an exit callback. */
5307 if (!job_need_end_check(job))
5308 {
5309 job_free(job);
5310 }
5311 else if (job->jv_channel != NULL)
5312 {
5313 /* Do remove the link to the channel, otherwise it hangs
5314 * around until Vim exits. See job_free() for refcount. */
5315 ch_log(job->jv_channel, "detaching channel from job");
5316 job->jv_channel->ch_job = NULL;
5317 channel_unref(job->jv_channel);
5318 job->jv_channel = NULL;
5319 }
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005320 }
5321 }
5322}
5323
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005324 int
5325free_unused_jobs_contents(int copyID, int mask)
5326{
5327 int did_free = FALSE;
5328 job_T *job;
5329
5330 for (job = first_job; job != NULL; job = job->jv_next)
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005331 if ((job->jv_copyID & mask) != (copyID & mask)
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005332 && !job_still_useful(job))
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005333 {
5334 /* Free the channel and ordinary items it contains, but don't
5335 * recurse into Lists, Dictionaries etc. */
5336 job_free_contents(job);
5337 did_free = TRUE;
Bram Moolenaar36e0f7d2016-05-08 13:21:12 +02005338 }
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005339 return did_free;
5340}
5341
5342 void
5343free_unused_jobs(int copyID, int mask)
5344{
5345 job_T *job;
5346 job_T *job_next;
5347
5348 for (job = first_job; job != NULL; job = job_next)
5349 {
5350 job_next = job->jv_next;
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005351 if ((job->jv_copyID & mask) != (copyID & mask)
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005352 && !job_still_useful(job))
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005353 {
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02005354 /* Free the job struct itself. */
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005355 job_free_job(job);
5356 }
5357 }
5358}
5359
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005360/*
5361 * Allocate a job. Sets the refcount to one and sets options default.
5362 */
Bram Moolenaar8f84c3a2017-07-22 16:14:44 +02005363 job_T *
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005364job_alloc(void)
5365{
5366 job_T *job;
5367
5368 job = (job_T *)alloc_clear(sizeof(job_T));
5369 if (job != NULL)
5370 {
5371 job->jv_refcount = 1;
5372 job->jv_stoponexit = vim_strsave((char_u *)"term");
5373
5374 if (first_job != NULL)
5375 {
5376 first_job->jv_prev = job;
5377 job->jv_next = first_job;
5378 }
5379 first_job = job;
5380 }
5381 return job;
5382}
5383
5384 void
5385job_set_options(job_T *job, jobopt_T *opt)
5386{
5387 if (opt->jo_set & JO_STOPONEXIT)
5388 {
5389 vim_free(job->jv_stoponexit);
5390 if (opt->jo_stoponexit == NULL || *opt->jo_stoponexit == NUL)
5391 job->jv_stoponexit = NULL;
5392 else
5393 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit);
5394 }
5395 if (opt->jo_set & JO_EXIT_CB)
5396 {
Bram Moolenaar1436d8d2016-07-11 22:41:15 +02005397 free_callback(job->jv_exit_cb, job->jv_exit_partial);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005398 if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL)
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005399 {
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005400 job->jv_exit_cb = NULL;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005401 job->jv_exit_partial = NULL;
5402 }
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005403 else
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005404 {
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005405 job->jv_exit_partial = opt->jo_exit_partial;
5406 if (job->jv_exit_partial != NULL)
Bram Moolenaar57e69ff2016-07-30 23:05:09 +02005407 {
5408 job->jv_exit_cb = opt->jo_exit_cb;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005409 ++job->jv_exit_partial->pt_refcount;
Bram Moolenaar57e69ff2016-07-30 23:05:09 +02005410 }
5411 else
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005412 {
Bram Moolenaar57e69ff2016-07-30 23:05:09 +02005413 job->jv_exit_cb = vim_strsave(opt->jo_exit_cb);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005414 func_ref(job->jv_exit_cb);
5415 }
Bram Moolenaar1735bc92016-03-14 23:05:14 +01005416 }
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005417 }
5418}
5419
5420/*
5421 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag.
5422 */
5423 void
Bram Moolenaarcf089462016-06-12 21:18:43 +02005424job_stop_on_exit(void)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005425{
5426 job_T *job;
5427
5428 for (job = first_job; job != NULL; job = job->jv_next)
5429 if (job->jv_status == JOB_STARTED && job->jv_stoponexit != NULL)
Bram Moolenaar2d33e902017-08-11 16:31:54 +02005430 mch_signal_job(job, job->jv_stoponexit);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005431}
5432
5433/*
Bram Moolenaar01688ad2016-10-27 20:00:07 +02005434 * Return TRUE when there is any job that has an exit callback and might exit,
5435 * which means job_check_ended() should be called more often.
Bram Moolenaarcf7c11a2016-06-02 20:05:26 +02005436 */
5437 int
Bram Moolenaarcf089462016-06-12 21:18:43 +02005438has_pending_job(void)
Bram Moolenaarcf7c11a2016-06-02 20:05:26 +02005439{
5440 job_T *job;
5441
5442 for (job = first_job; job != NULL; job = job->jv_next)
Bram Moolenaar01688ad2016-10-27 20:00:07 +02005443 /* Only should check if the channel has been closed, if the channel is
5444 * open the job won't exit. */
Bram Moolenaar4e9d4432018-04-24 20:54:07 +02005445 if ((job->jv_status == JOB_STARTED && !job_channel_still_useful(job))
5446 || (job->jv_status == JOB_FINISHED
5447 && job_channel_can_close(job)))
Bram Moolenaarcf7c11a2016-06-02 20:05:26 +02005448 return TRUE;
5449 return FALSE;
5450}
5451
Bram Moolenaar97792de2016-10-15 18:36:49 +02005452#define MAX_CHECK_ENDED 8
5453
Bram Moolenaarcf7c11a2016-06-02 20:05:26 +02005454/*
Bram Moolenaar36e0f7d2016-05-08 13:21:12 +02005455 * Called once in a while: check if any jobs that seem useful have ended.
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005456 */
5457 void
5458job_check_ended(void)
5459{
Bram Moolenaar97792de2016-10-15 18:36:49 +02005460 int i;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005461
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005462 if (first_job == NULL)
5463 return;
5464
Bram Moolenaar97792de2016-10-15 18:36:49 +02005465 for (i = 0; i < MAX_CHECK_ENDED; ++i)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005466 {
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005467 /* NOTE: mch_detect_ended_job() must only return a job of which the
5468 * status was just set to JOB_ENDED. */
Bram Moolenaar97792de2016-10-15 18:36:49 +02005469 job_T *job = mch_detect_ended_job(first_job);
5470
5471 if (job == NULL)
5472 break;
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005473 job_cleanup(job); /* may free "job" */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005474 }
Bram Moolenaar97792de2016-10-15 18:36:49 +02005475
Bram Moolenaarcf7c11a2016-06-02 20:05:26 +02005476 if (channel_need_redraw)
5477 {
5478 channel_need_redraw = FALSE;
Bram Moolenaar02e177d2017-08-26 23:43:28 +02005479 redraw_after_callback(TRUE);
Bram Moolenaarcf7c11a2016-06-02 20:05:26 +02005480 }
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005481}
5482
5483/*
Bram Moolenaar96ca27a2017-07-17 23:20:24 +02005484 * Create a job and return it. Implements job_start().
Bram Moolenaar13568252018-03-16 20:46:58 +01005485 * "argv_arg" is only for Unix.
5486 * When "argv_arg" is NULL then "argvars" is used.
Bram Moolenaar96ca27a2017-07-17 23:20:24 +02005487 * The returned job has a refcount of one.
5488 * Returns NULL when out of memory.
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005489 */
5490 job_T *
Bram Moolenaar13568252018-03-16 20:46:58 +01005491job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005492{
5493 job_T *job;
5494 char_u *cmd = NULL;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005495 char **argv = NULL;
5496 int argc = 0;
Bram Moolenaar20608922018-04-21 22:30:08 +02005497#if defined(UNIX)
5498# define USE_ARGV
Bram Moolenaar850d4272018-04-30 10:38:40 +02005499 int i;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005500#else
5501 garray_T ga;
5502#endif
5503 jobopt_T opt;
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02005504 ch_part_T part;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005505
5506 job = job_alloc();
5507 if (job == NULL)
5508 return NULL;
5509
5510 job->jv_status = JOB_FAILED;
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005511#ifndef USE_ARGV
5512 ga_init2(&ga, (int)sizeof(char*), 20);
5513#endif
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005514
Bram Moolenaarcb8bbe92017-07-16 13:48:22 +02005515 if (opt_arg != NULL)
5516 opt = *opt_arg;
5517 else
5518 {
5519 /* Default mode is NL. */
5520 clear_job_options(&opt);
5521 opt.jo_mode = MODE_NL;
5522 if (get_job_options(&argvars[1], &opt,
Bram Moolenaar8ed54002017-08-11 22:22:36 +02005523 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT
5524 + JO_EXIT_CB + JO_OUT_IO + JO_BLOCK_WRITE,
5525 JO2_ENV + JO2_CWD) == FAIL)
Bram Moolenaar3c3a80d2017-08-03 17:06:45 +02005526 goto theend;
Bram Moolenaarcb8bbe92017-07-16 13:48:22 +02005527 }
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005528
5529 /* Check that when io is "file" that there is a file name. */
Bram Moolenaardc0ccae2016-10-09 17:28:01 +02005530 for (part = PART_OUT; part < PART_COUNT; ++part)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005531 if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT)))
5532 && opt.jo_io[part] == JIO_FILE
5533 && (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT)))
5534 || *opt.jo_io_name[part] == NUL))
5535 {
Bram Moolenaard6c2f052016-03-14 23:22:59 +01005536 EMSG(_("E920: _io file requires _name to be set"));
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005537 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005538 }
5539
5540 if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER)
5541 {
5542 buf_T *buf = NULL;
5543
5544 /* check that we can find the buffer before starting the job */
5545 if (opt.jo_set & JO_IN_BUF)
5546 {
5547 buf = buflist_findnr(opt.jo_io_buf[PART_IN]);
5548 if (buf == NULL)
5549 EMSGN(_(e_nobufnr), (long)opt.jo_io_buf[PART_IN]);
5550 }
5551 else if (!(opt.jo_set & JO_IN_NAME))
5552 {
Bram Moolenaard6c2f052016-03-14 23:22:59 +01005553 EMSG(_("E915: in_io buffer requires in_buf or in_name to be set"));
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005554 }
5555 else
5556 buf = buflist_find_by_name(opt.jo_io_name[PART_IN], FALSE);
5557 if (buf == NULL)
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005558 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005559 if (buf->b_ml.ml_mfp == NULL)
5560 {
5561 char_u numbuf[NUMBUFLEN];
5562 char_u *s;
5563
5564 if (opt.jo_set & JO_IN_BUF)
5565 {
5566 sprintf((char *)numbuf, "%d", opt.jo_io_buf[PART_IN]);
5567 s = numbuf;
5568 }
5569 else
5570 s = opt.jo_io_name[PART_IN];
5571 EMSG2(_("E918: buffer must be loaded: %s"), s);
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005572 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005573 }
5574 job->jv_in_buf = buf;
5575 }
5576
5577 job_set_options(job, &opt);
5578
Bram Moolenaar13568252018-03-16 20:46:58 +01005579#ifdef USE_ARGV
5580 if (argv_arg != NULL)
5581 {
Bram Moolenaar20608922018-04-21 22:30:08 +02005582 /* Make a copy of argv_arg for job->jv_argv. */
5583 for (i = 0; argv_arg[i] != NULL; i++)
5584 argc++;
5585 argv = (char **)alloc(sizeof(char_u *) * (argc + 1));
5586 if (argv == NULL)
5587 goto theend;
5588 for (i = 0; i < argc; i++)
5589 argv[i] = (char *)vim_strsave((char_u *)argv_arg[i]);
5590 argv[argc] = NULL;
Bram Moolenaar13568252018-03-16 20:46:58 +01005591 }
5592 else
5593#endif
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005594 if (argvars[0].v_type == VAR_STRING)
5595 {
5596 /* Command is a string. */
5597 cmd = argvars[0].vval.v_string;
Bram Moolenaar80385682016-03-27 19:13:35 +02005598 if (cmd == NULL || *cmd == NUL)
5599 {
5600 EMSG(_(e_invarg));
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005601 goto theend;
Bram Moolenaar80385682016-03-27 19:13:35 +02005602 }
Bram Moolenaarebe74b72018-04-21 23:34:43 +02005603
5604 if (build_argv_from_string(cmd, &argv, &argc) == FAIL)
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005605 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005606 }
5607 else if (argvars[0].v_type != VAR_LIST
5608 || argvars[0].vval.v_list == NULL
5609 || argvars[0].vval.v_list->lv_len < 1)
5610 {
5611 EMSG(_(e_invarg));
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005612 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005613 }
5614 else
5615 {
Bram Moolenaarebe74b72018-04-21 23:34:43 +02005616 list_T *l = argvars[0].vval.v_list;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005617
Bram Moolenaarebe74b72018-04-21 23:34:43 +02005618 if (build_argv_from_list(l, &argv, &argc) == FAIL)
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005619 goto theend;
Bram Moolenaar20608922018-04-21 22:30:08 +02005620#ifndef USE_ARGV
Bram Moolenaardcaa6132017-08-13 17:13:09 +02005621 if (win32_build_cmd(l, &ga) == FAIL)
5622 goto theend;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005623 cmd = ga.ga_data;
5624#endif
5625 }
5626
Bram Moolenaar20608922018-04-21 22:30:08 +02005627 /* Save the command used to start the job. */
5628 job->jv_argv = (char_u **)argv;
Bram Moolenaare1fc5152018-04-21 19:49:08 +02005629
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005630#ifdef USE_ARGV
5631 if (ch_log_active())
5632 {
5633 garray_T ga;
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005634
5635 ga_init2(&ga, (int)sizeof(char), 200);
5636 for (i = 0; i < argc; ++i)
5637 {
5638 if (i > 0)
5639 ga_concat(&ga, (char_u *)" ");
5640 ga_concat(&ga, (char_u *)argv[i]);
5641 }
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02005642 ch_log(NULL, "Starting job: %s", (char *)ga.ga_data);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005643 ga_clear(&ga);
5644 }
Bram Moolenaar5a1feb82017-07-22 18:04:08 +02005645 mch_job_start(argv, job, &opt);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005646#else
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02005647 ch_log(NULL, "Starting job: %s", (char *)cmd);
Bram Moolenaar5a1feb82017-07-22 18:04:08 +02005648 mch_job_start((char *)cmd, job, &opt);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005649#endif
5650
5651 /* If the channel is reading from a buffer, write lines now. */
5652 if (job->jv_channel != NULL)
5653 channel_write_in(job->jv_channel);
5654
5655theend:
Bram Moolenaar20608922018-04-21 22:30:08 +02005656#ifndef USE_ARGV
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005657 vim_free(ga.ga_data);
5658#endif
Bram Moolenaar20608922018-04-21 22:30:08 +02005659 if ((char_u **)argv != job->jv_argv)
5660 vim_free(argv);
Bram Moolenaar0e4c1de2016-04-07 21:40:38 +02005661 free_job_options(&opt);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005662 return job;
5663}
5664
5665/*
5666 * Get the status of "job" and invoke the exit callback when needed.
5667 * The returned string is not allocated.
5668 */
5669 char *
5670job_status(job_T *job)
5671{
5672 char *result;
5673
Bram Moolenaar7df915d2016-11-17 17:25:32 +01005674 if (job->jv_status >= JOB_ENDED)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005675 /* No need to check, dead is dead. */
5676 result = "dead";
5677 else if (job->jv_status == JOB_FAILED)
5678 result = "fail";
5679 else
5680 {
5681 result = mch_job_status(job);
5682 if (job->jv_status == JOB_ENDED)
Bram Moolenaar97792de2016-10-15 18:36:49 +02005683 job_cleanup(job);
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005684 }
5685 return result;
5686}
5687
Bram Moolenaar8950a562016-03-12 15:22:55 +01005688/*
5689 * Implementation of job_info().
5690 */
5691 void
5692job_info(job_T *job, dict_T *dict)
5693{
5694 dictitem_T *item;
5695 varnumber_T nr;
Bram Moolenaare1fc5152018-04-21 19:49:08 +02005696 list_T *l;
5697 int i;
Bram Moolenaar8950a562016-03-12 15:22:55 +01005698
5699 dict_add_nr_str(dict, "status", 0L, (char_u *)job_status(job));
5700
5701 item = dictitem_alloc((char_u *)"channel");
5702 if (item == NULL)
5703 return;
5704 item->di_tv.v_lock = 0;
5705 item->di_tv.v_type = VAR_CHANNEL;
5706 item->di_tv.vval.v_channel = job->jv_channel;
5707 if (job->jv_channel != NULL)
5708 ++job->jv_channel->ch_refcount;
5709 if (dict_add(dict, item) == FAIL)
5710 dictitem_free(item);
5711
5712#ifdef UNIX
5713 nr = job->jv_pid;
5714#else
5715 nr = job->jv_proc_info.dwProcessId;
5716#endif
5717 dict_add_nr_str(dict, "process", nr, NULL);
Bram Moolenaar2dc9d262017-09-08 14:39:30 +02005718 dict_add_nr_str(dict, "tty_in", 0L,
5719 job->jv_tty_in != NULL ? job->jv_tty_in : (char_u *)"");
5720 dict_add_nr_str(dict, "tty_out", 0L,
5721 job->jv_tty_out != NULL ? job->jv_tty_out : (char_u *)"");
Bram Moolenaar8950a562016-03-12 15:22:55 +01005722
5723 dict_add_nr_str(dict, "exitval", job->jv_exitval, NULL);
Bram Moolenaard6c2f052016-03-14 23:22:59 +01005724 dict_add_nr_str(dict, "exit_cb", 0L, job->jv_exit_cb);
Bram Moolenaar8950a562016-03-12 15:22:55 +01005725 dict_add_nr_str(dict, "stoponexit", 0L, job->jv_stoponexit);
Bram Moolenaare1fc5152018-04-21 19:49:08 +02005726
5727 l = list_alloc();
5728 if (l != NULL)
5729 {
5730 dict_add_list(dict, "cmd", l);
Bram Moolenaar20608922018-04-21 22:30:08 +02005731 if (job->jv_argv != NULL)
5732 for (i = 0; job->jv_argv[i] != NULL; i++)
5733 list_append_string(l, job->jv_argv[i], -1);
Bram Moolenaare1fc5152018-04-21 19:49:08 +02005734 }
5735}
5736
5737/*
5738 * Implementation of job_info() to return info for all jobs.
5739 */
5740 void
5741job_info_all(list_T *l)
5742{
5743 job_T *job;
5744 typval_T tv;
5745
5746 for (job = first_job; job != NULL; job = job->jv_next)
5747 {
5748 tv.v_type = VAR_JOB;
5749 tv.vval.v_job = job;
5750
5751 if (list_append_tv(l, &tv) != OK)
5752 return;
5753 }
Bram Moolenaar8950a562016-03-12 15:22:55 +01005754}
5755
Bram Moolenaar96ca27a2017-07-17 23:20:24 +02005756/*
5757 * Send a signal to "job". Implements job_stop().
5758 * When "type" is not NULL use this for the type.
5759 * Otherwise use argvars[1] for the type.
5760 */
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005761 int
Bram Moolenaar96ca27a2017-07-17 23:20:24 +02005762job_stop(job_T *job, typval_T *argvars, char *type)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005763{
5764 char_u *arg;
5765
Bram Moolenaar96ca27a2017-07-17 23:20:24 +02005766 if (type != NULL)
5767 arg = (char_u *)type;
5768 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005769 arg = (char_u *)"";
5770 else
5771 {
5772 arg = get_tv_string_chk(&argvars[1]);
5773 if (arg == NULL)
5774 {
5775 EMSG(_(e_invarg));
5776 return 0;
5777 }
5778 }
Bram Moolenaar61a66052017-07-22 18:39:00 +02005779 if (job->jv_status == JOB_FAILED)
5780 {
5781 ch_log(job->jv_channel, "Job failed to start, job_stop() skipped");
5782 return 0;
5783 }
Bram Moolenaar1a9020d2017-04-29 16:24:38 +02005784 if (job->jv_status == JOB_ENDED)
5785 {
5786 ch_log(job->jv_channel, "Job has already ended, job_stop() skipped");
5787 return 0;
5788 }
Bram Moolenaar2f3a90a2017-08-03 14:49:29 +02005789 ch_log(job->jv_channel, "Stopping job with '%s'", (char *)arg);
Bram Moolenaar2d33e902017-08-11 16:31:54 +02005790 if (mch_signal_job(job, arg) == FAIL)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005791 return 0;
5792
Bram Moolenaar1a9020d2017-04-29 16:24:38 +02005793 /* Assume that only "kill" will kill the job. */
5794 if (job->jv_channel != NULL && STRCMP(arg, "kill") == 0)
Bram Moolenaar8e2c9422016-03-12 13:43:33 +01005795 job->jv_channel->ch_job_killed = TRUE;
5796
5797 /* We don't try freeing the job, obviously the caller still has a
5798 * reference to it. */
5799 return 1;
5800}
5801
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01005802#endif /* FEAT_JOB_CHANNEL */