Mercurial > vim
comparison src/channel.c @ 17170:cee12488e4bc v8.1.1584
patch 8.1.1584: the evalfunc.c file is getting too big
commit https://github.com/vim/vim/commit/0a1f56fcfe31be929e9cd8c3d81a984c960e4180
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Jun 24 00:43:35 2019 +0200
patch 8.1.1584: the evalfunc.c file is getting too big
Problem: The evalfunc.c file is getting too big.
Solution: Move channel and job related functions to channel.c.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 24 Jun 2019 00:45:04 +0200 |
parents | ebe9aab81898 |
children | fd983b381ec0 |
comparison
equal
deleted
inserted
replaced
17169:c06b3187f7dc | 17170:cee12488e4bc |
---|---|
950 | 950 |
951 return channel; | 951 return channel; |
952 } | 952 } |
953 | 953 |
954 /* | 954 /* |
955 * Implements ch_open(). | 955 * Copy callback from "src" to "dest", incrementing the refcounts. |
956 */ | 956 */ |
957 channel_T * | |
958 channel_open_func(typval_T *argvars) | |
959 { | |
960 char_u *address; | |
961 char_u *p; | |
962 char *rest; | |
963 int port; | |
964 jobopt_T opt; | |
965 channel_T *channel = NULL; | |
966 | |
967 address = tv_get_string(&argvars[0]); | |
968 if (argvars[1].v_type != VAR_UNKNOWN | |
969 && (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)) | |
970 { | |
971 emsg(_(e_invarg)); | |
972 return NULL; | |
973 } | |
974 | |
975 /* parse address */ | |
976 p = vim_strchr(address, ':'); | |
977 if (p == NULL) | |
978 { | |
979 semsg(_(e_invarg2), address); | |
980 return NULL; | |
981 } | |
982 *p++ = NUL; | |
983 port = strtol((char *)p, &rest, 10); | |
984 if (*address == NUL || port <= 0 || *rest != NUL) | |
985 { | |
986 p[-1] = ':'; | |
987 semsg(_(e_invarg2), address); | |
988 return NULL; | |
989 } | |
990 | |
991 /* parse options */ | |
992 clear_job_options(&opt); | |
993 opt.jo_mode = MODE_JSON; | |
994 opt.jo_timeout = 2000; | |
995 if (get_job_options(&argvars[1], &opt, | |
996 JO_MODE_ALL + JO_CB_ALL + JO_WAITTIME + JO_TIMEOUT_ALL, 0) == FAIL) | |
997 goto theend; | |
998 if (opt.jo_timeout < 0) | |
999 { | |
1000 emsg(_(e_invarg)); | |
1001 goto theend; | |
1002 } | |
1003 | |
1004 channel = channel_open((char *)address, port, opt.jo_waittime, NULL); | |
1005 if (channel != NULL) | |
1006 { | |
1007 opt.jo_set = JO_ALL; | |
1008 channel_set_options(channel, &opt); | |
1009 } | |
1010 theend: | |
1011 free_job_options(&opt); | |
1012 return channel; | |
1013 } | |
1014 | |
1015 static void | 957 static void |
1016 ch_close_part(channel_T *channel, ch_part_T part) | 958 copy_callback(callback_T *dest, callback_T *src) |
1017 { | 959 { |
1018 sock_T *fd = &channel->ch_part[part].ch_fd; | 960 dest->cb_partial = src->cb_partial; |
1019 | 961 if (dest->cb_partial != NULL) |
1020 if (*fd != INVALID_FD) | 962 { |
1021 { | 963 dest->cb_name = src->cb_name; |
1022 if (part == PART_SOCK) | 964 dest->cb_free_name = FALSE; |
1023 sock_close(*fd); | 965 ++dest->cb_partial->pt_refcount; |
1024 else | 966 } |
1025 { | 967 else |
1026 /* When using a pty the same FD is set on multiple parts, only | 968 { |
1027 * close it when the last reference is closed. */ | 969 dest->cb_name = vim_strsave(src->cb_name); |
1028 if ((part == PART_IN || channel->CH_IN_FD != *fd) | 970 dest->cb_free_name = TRUE; |
1029 && (part == PART_OUT || channel->CH_OUT_FD != *fd) | 971 func_ref(src->cb_name); |
1030 && (part == PART_ERR || channel->CH_ERR_FD != *fd)) | 972 } |
1031 { | 973 } |
1032 #ifdef MSWIN | 974 |
1033 if (channel->ch_named_pipe) | 975 static void |
1034 DisconnectNamedPipe((HANDLE)fd); | 976 free_set_callback(callback_T *cbp, callback_T *callback) |
1035 #endif | 977 { |
1036 fd_close(*fd); | 978 free_callback(cbp); |
1037 } | 979 |
1038 } | 980 if (callback->cb_name != NULL && *callback->cb_name != NUL) |
1039 *fd = INVALID_FD; | 981 copy_callback(cbp, callback); |
1040 | 982 else |
1041 /* channel is closed, may want to end the job if it was the last */ | 983 cbp->cb_name = NULL; |
1042 channel->ch_to_be_closed &= ~(1U << part); | |
1043 } | |
1044 } | |
1045 | |
1046 void | |
1047 channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err) | |
1048 { | |
1049 if (in != INVALID_FD) | |
1050 { | |
1051 ch_close_part(channel, PART_IN); | |
1052 channel->CH_IN_FD = in; | |
1053 # if defined(UNIX) | |
1054 /* Do not end the job when all output channels are closed, wait until | |
1055 * the job ended. */ | |
1056 if (mch_isatty(in)) | |
1057 channel->ch_to_be_closed |= (1U << PART_IN); | |
1058 # endif | |
1059 } | |
1060 if (out != INVALID_FD) | |
1061 { | |
1062 # if defined(FEAT_GUI) | |
1063 channel_gui_unregister_one(channel, PART_OUT); | |
1064 # endif | |
1065 ch_close_part(channel, PART_OUT); | |
1066 channel->CH_OUT_FD = out; | |
1067 channel->ch_to_be_closed |= (1U << PART_OUT); | |
1068 # if defined(FEAT_GUI) | |
1069 channel_gui_register_one(channel, PART_OUT); | |
1070 # endif | |
1071 } | |
1072 if (err != INVALID_FD) | |
1073 { | |
1074 # if defined(FEAT_GUI) | |
1075 channel_gui_unregister_one(channel, PART_ERR); | |
1076 # endif | |
1077 ch_close_part(channel, PART_ERR); | |
1078 channel->CH_ERR_FD = err; | |
1079 channel->ch_to_be_closed |= (1U << PART_ERR); | |
1080 # if defined(FEAT_GUI) | |
1081 channel_gui_register_one(channel, PART_ERR); | |
1082 # endif | |
1083 } | |
1084 } | |
1085 | |
1086 /* | |
1087 * Sets the job the channel is associated with and associated options. | |
1088 * This does not keep a refcount, when the job is freed ch_job is cleared. | |
1089 */ | |
1090 void | |
1091 channel_set_job(channel_T *channel, job_T *job, jobopt_T *options) | |
1092 { | |
1093 channel->ch_job = job; | |
1094 | |
1095 channel_set_options(channel, options); | |
1096 | |
1097 if (job->jv_in_buf != NULL) | |
1098 { | |
1099 chanpart_T *in_part = &channel->ch_part[PART_IN]; | |
1100 | |
1101 set_bufref(&in_part->ch_bufref, job->jv_in_buf); | |
1102 ch_log(channel, "reading from buffer '%s'", | |
1103 (char *)in_part->ch_bufref.br_buf->b_ffname); | |
1104 if (options->jo_set & JO_IN_TOP) | |
1105 { | |
1106 if (options->jo_in_top == 0 && !(options->jo_set & JO_IN_BOT)) | |
1107 { | |
1108 /* Special mode: send last-but-one line when appending a line | |
1109 * to the buffer. */ | |
1110 in_part->ch_bufref.br_buf->b_write_to_channel = TRUE; | |
1111 in_part->ch_buf_append = TRUE; | |
1112 in_part->ch_buf_top = | |
1113 in_part->ch_bufref.br_buf->b_ml.ml_line_count + 1; | |
1114 } | |
1115 else | |
1116 in_part->ch_buf_top = options->jo_in_top; | |
1117 } | |
1118 else | |
1119 in_part->ch_buf_top = 1; | |
1120 if (options->jo_set & JO_IN_BOT) | |
1121 in_part->ch_buf_bot = options->jo_in_bot; | |
1122 else | |
1123 in_part->ch_buf_bot = in_part->ch_bufref.br_buf->b_ml.ml_line_count; | |
1124 } | |
1125 } | 984 } |
1126 | 985 |
1127 /* | 986 /* |
1128 * Prepare buffer "buf" for writing channel output to. | 987 * Prepare buffer "buf" for writing channel output to. |
1129 */ | 988 */ |
1177 | 1036 |
1178 return buf; | 1037 return buf; |
1179 } | 1038 } |
1180 | 1039 |
1181 /* | 1040 /* |
1182 * Copy callback from "src" to "dest", incrementing the refcounts. | 1041 * Set various properties from an "opt" argument. |
1183 */ | 1042 */ |
1184 static void | 1043 static void |
1185 copy_callback(callback_T *dest, callback_T *src) | |
1186 { | |
1187 dest->cb_partial = src->cb_partial; | |
1188 if (dest->cb_partial != NULL) | |
1189 { | |
1190 dest->cb_name = src->cb_name; | |
1191 dest->cb_free_name = FALSE; | |
1192 ++dest->cb_partial->pt_refcount; | |
1193 } | |
1194 else | |
1195 { | |
1196 dest->cb_name = vim_strsave(src->cb_name); | |
1197 dest->cb_free_name = TRUE; | |
1198 func_ref(src->cb_name); | |
1199 } | |
1200 } | |
1201 | |
1202 static void | |
1203 free_set_callback(callback_T *cbp, callback_T *callback) | |
1204 { | |
1205 free_callback(cbp); | |
1206 | |
1207 if (callback->cb_name != NULL && *callback->cb_name != NUL) | |
1208 copy_callback(cbp, callback); | |
1209 else | |
1210 cbp->cb_name = NULL; | |
1211 } | |
1212 | |
1213 /* | |
1214 * Set various properties from an "opt" argument. | |
1215 */ | |
1216 void | |
1217 channel_set_options(channel_T *channel, jobopt_T *opt) | 1044 channel_set_options(channel_T *channel, jobopt_T *opt) |
1218 { | 1045 { |
1219 ch_part_T part; | 1046 ch_part_T part; |
1220 | 1047 |
1221 if (opt->jo_set & JO_MODE) | 1048 if (opt->jo_set & JO_MODE) |
1341 } | 1168 } |
1342 | 1169 |
1343 channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT]; | 1170 channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT]; |
1344 channel->ch_part[PART_ERR].ch_io = opt->jo_io[PART_ERR]; | 1171 channel->ch_part[PART_ERR].ch_io = opt->jo_io[PART_ERR]; |
1345 channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN]; | 1172 channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN]; |
1173 } | |
1174 | |
1175 /* | |
1176 * Implements ch_open(). | |
1177 */ | |
1178 channel_T * | |
1179 channel_open_func(typval_T *argvars) | |
1180 { | |
1181 char_u *address; | |
1182 char_u *p; | |
1183 char *rest; | |
1184 int port; | |
1185 jobopt_T opt; | |
1186 channel_T *channel = NULL; | |
1187 | |
1188 address = tv_get_string(&argvars[0]); | |
1189 if (argvars[1].v_type != VAR_UNKNOWN | |
1190 && (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)) | |
1191 { | |
1192 emsg(_(e_invarg)); | |
1193 return NULL; | |
1194 } | |
1195 | |
1196 /* parse address */ | |
1197 p = vim_strchr(address, ':'); | |
1198 if (p == NULL) | |
1199 { | |
1200 semsg(_(e_invarg2), address); | |
1201 return NULL; | |
1202 } | |
1203 *p++ = NUL; | |
1204 port = strtol((char *)p, &rest, 10); | |
1205 if (*address == NUL || port <= 0 || *rest != NUL) | |
1206 { | |
1207 p[-1] = ':'; | |
1208 semsg(_(e_invarg2), address); | |
1209 return NULL; | |
1210 } | |
1211 | |
1212 /* parse options */ | |
1213 clear_job_options(&opt); | |
1214 opt.jo_mode = MODE_JSON; | |
1215 opt.jo_timeout = 2000; | |
1216 if (get_job_options(&argvars[1], &opt, | |
1217 JO_MODE_ALL + JO_CB_ALL + JO_WAITTIME + JO_TIMEOUT_ALL, 0) == FAIL) | |
1218 goto theend; | |
1219 if (opt.jo_timeout < 0) | |
1220 { | |
1221 emsg(_(e_invarg)); | |
1222 goto theend; | |
1223 } | |
1224 | |
1225 channel = channel_open((char *)address, port, opt.jo_waittime, NULL); | |
1226 if (channel != NULL) | |
1227 { | |
1228 opt.jo_set = JO_ALL; | |
1229 channel_set_options(channel, &opt); | |
1230 } | |
1231 theend: | |
1232 free_job_options(&opt); | |
1233 return channel; | |
1234 } | |
1235 | |
1236 static void | |
1237 ch_close_part(channel_T *channel, ch_part_T part) | |
1238 { | |
1239 sock_T *fd = &channel->ch_part[part].ch_fd; | |
1240 | |
1241 if (*fd != INVALID_FD) | |
1242 { | |
1243 if (part == PART_SOCK) | |
1244 sock_close(*fd); | |
1245 else | |
1246 { | |
1247 /* When using a pty the same FD is set on multiple parts, only | |
1248 * close it when the last reference is closed. */ | |
1249 if ((part == PART_IN || channel->CH_IN_FD != *fd) | |
1250 && (part == PART_OUT || channel->CH_OUT_FD != *fd) | |
1251 && (part == PART_ERR || channel->CH_ERR_FD != *fd)) | |
1252 { | |
1253 #ifdef MSWIN | |
1254 if (channel->ch_named_pipe) | |
1255 DisconnectNamedPipe((HANDLE)fd); | |
1256 #endif | |
1257 fd_close(*fd); | |
1258 } | |
1259 } | |
1260 *fd = INVALID_FD; | |
1261 | |
1262 /* channel is closed, may want to end the job if it was the last */ | |
1263 channel->ch_to_be_closed &= ~(1U << part); | |
1264 } | |
1265 } | |
1266 | |
1267 void | |
1268 channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err) | |
1269 { | |
1270 if (in != INVALID_FD) | |
1271 { | |
1272 ch_close_part(channel, PART_IN); | |
1273 channel->CH_IN_FD = in; | |
1274 # if defined(UNIX) | |
1275 /* Do not end the job when all output channels are closed, wait until | |
1276 * the job ended. */ | |
1277 if (mch_isatty(in)) | |
1278 channel->ch_to_be_closed |= (1U << PART_IN); | |
1279 # endif | |
1280 } | |
1281 if (out != INVALID_FD) | |
1282 { | |
1283 # if defined(FEAT_GUI) | |
1284 channel_gui_unregister_one(channel, PART_OUT); | |
1285 # endif | |
1286 ch_close_part(channel, PART_OUT); | |
1287 channel->CH_OUT_FD = out; | |
1288 channel->ch_to_be_closed |= (1U << PART_OUT); | |
1289 # if defined(FEAT_GUI) | |
1290 channel_gui_register_one(channel, PART_OUT); | |
1291 # endif | |
1292 } | |
1293 if (err != INVALID_FD) | |
1294 { | |
1295 # if defined(FEAT_GUI) | |
1296 channel_gui_unregister_one(channel, PART_ERR); | |
1297 # endif | |
1298 ch_close_part(channel, PART_ERR); | |
1299 channel->CH_ERR_FD = err; | |
1300 channel->ch_to_be_closed |= (1U << PART_ERR); | |
1301 # if defined(FEAT_GUI) | |
1302 channel_gui_register_one(channel, PART_ERR); | |
1303 # endif | |
1304 } | |
1305 } | |
1306 | |
1307 /* | |
1308 * Sets the job the channel is associated with and associated options. | |
1309 * This does not keep a refcount, when the job is freed ch_job is cleared. | |
1310 */ | |
1311 void | |
1312 channel_set_job(channel_T *channel, job_T *job, jobopt_T *options) | |
1313 { | |
1314 channel->ch_job = job; | |
1315 | |
1316 channel_set_options(channel, options); | |
1317 | |
1318 if (job->jv_in_buf != NULL) | |
1319 { | |
1320 chanpart_T *in_part = &channel->ch_part[PART_IN]; | |
1321 | |
1322 set_bufref(&in_part->ch_bufref, job->jv_in_buf); | |
1323 ch_log(channel, "reading from buffer '%s'", | |
1324 (char *)in_part->ch_bufref.br_buf->b_ffname); | |
1325 if (options->jo_set & JO_IN_TOP) | |
1326 { | |
1327 if (options->jo_in_top == 0 && !(options->jo_set & JO_IN_BOT)) | |
1328 { | |
1329 /* Special mode: send last-but-one line when appending a line | |
1330 * to the buffer. */ | |
1331 in_part->ch_bufref.br_buf->b_write_to_channel = TRUE; | |
1332 in_part->ch_buf_append = TRUE; | |
1333 in_part->ch_buf_top = | |
1334 in_part->ch_bufref.br_buf->b_ml.ml_line_count + 1; | |
1335 } | |
1336 else | |
1337 in_part->ch_buf_top = options->jo_in_top; | |
1338 } | |
1339 else | |
1340 in_part->ch_buf_top = 1; | |
1341 if (options->jo_set & JO_IN_BOT) | |
1342 in_part->ch_buf_bot = options->jo_in_bot; | |
1343 else | |
1344 in_part->ch_buf_bot = in_part->ch_bufref.br_buf->b_ml.ml_line_count; | |
1345 } | |
1346 } | 1346 } |
1347 | 1347 |
1348 /* | 1348 /* |
1349 * Set the callback for "channel"/"part" for the response with "id". | 1349 * Set the callback for "channel"/"part" for the response with "id". |
1350 */ | 1350 */ |
3622 } | 3622 } |
3623 } | 3623 } |
3624 if (id >= 0) | 3624 if (id >= 0) |
3625 channel_remove_block_id(chanpart, id); | 3625 channel_remove_block_id(chanpart, id); |
3626 return FAIL; | 3626 return FAIL; |
3627 } | |
3628 | |
3629 /* | |
3630 * Get the channel from the argument. | |
3631 * Returns NULL if the handle is invalid. | |
3632 * When "check_open" is TRUE check that the channel can be used. | |
3633 * When "reading" is TRUE "check_open" considers typeahead useful. | |
3634 * "part" is used to check typeahead, when PART_COUNT use the default part. | |
3635 */ | |
3636 static channel_T * | |
3637 get_channel_arg(typval_T *tv, int check_open, int reading, ch_part_T part) | |
3638 { | |
3639 channel_T *channel = NULL; | |
3640 int has_readahead = FALSE; | |
3641 | |
3642 if (tv->v_type == VAR_JOB) | |
3643 { | |
3644 if (tv->vval.v_job != NULL) | |
3645 channel = tv->vval.v_job->jv_channel; | |
3646 } | |
3647 else if (tv->v_type == VAR_CHANNEL) | |
3648 { | |
3649 channel = tv->vval.v_channel; | |
3650 } | |
3651 else | |
3652 { | |
3653 semsg(_(e_invarg2), tv_get_string(tv)); | |
3654 return NULL; | |
3655 } | |
3656 if (channel != NULL && reading) | |
3657 has_readahead = channel_has_readahead(channel, | |
3658 part != PART_COUNT ? part : channel_part_read(channel)); | |
3659 | |
3660 if (check_open && (channel == NULL || (!channel_is_open(channel) | |
3661 && !(reading && has_readahead)))) | |
3662 { | |
3663 emsg(_("E906: not an open channel")); | |
3664 return NULL; | |
3665 } | |
3666 return channel; | |
3627 } | 3667 } |
3628 | 3668 |
3629 /* | 3669 /* |
3630 * Common for ch_read() and ch_readraw(). | 3670 * Common for ch_read() and ch_readraw(). |
3631 */ | 3671 */ |
5191 } | 5231 } |
5192 | 5232 |
5193 return OK; | 5233 return OK; |
5194 } | 5234 } |
5195 | 5235 |
5196 /* | |
5197 * Get the channel from the argument. | |
5198 * Returns NULL if the handle is invalid. | |
5199 * When "check_open" is TRUE check that the channel can be used. | |
5200 * When "reading" is TRUE "check_open" considers typeahead useful. | |
5201 * "part" is used to check typeahead, when PART_COUNT use the default part. | |
5202 */ | |
5203 channel_T * | |
5204 get_channel_arg(typval_T *tv, int check_open, int reading, ch_part_T part) | |
5205 { | |
5206 channel_T *channel = NULL; | |
5207 int has_readahead = FALSE; | |
5208 | |
5209 if (tv->v_type == VAR_JOB) | |
5210 { | |
5211 if (tv->vval.v_job != NULL) | |
5212 channel = tv->vval.v_job->jv_channel; | |
5213 } | |
5214 else if (tv->v_type == VAR_CHANNEL) | |
5215 { | |
5216 channel = tv->vval.v_channel; | |
5217 } | |
5218 else | |
5219 { | |
5220 semsg(_(e_invarg2), tv_get_string(tv)); | |
5221 return NULL; | |
5222 } | |
5223 if (channel != NULL && reading) | |
5224 has_readahead = channel_has_readahead(channel, | |
5225 part != PART_COUNT ? part : channel_part_read(channel)); | |
5226 | |
5227 if (check_open && (channel == NULL || (!channel_is_open(channel) | |
5228 && !(reading && has_readahead)))) | |
5229 { | |
5230 emsg(_("E906: not an open channel")); | |
5231 return NULL; | |
5232 } | |
5233 return channel; | |
5234 } | |
5235 | |
5236 static job_T *first_job = NULL; | 5236 static job_T *first_job = NULL; |
5237 | 5237 |
5238 static void | 5238 static void |
5239 job_free_contents(job_T *job) | 5239 job_free_contents(job_T *job) |
5240 { | 5240 { |
5974 } | 5974 } |
5975 return result; | 5975 return result; |
5976 } | 5976 } |
5977 | 5977 |
5978 /* | 5978 /* |
5979 * Implementation of job_info(). | |
5980 */ | |
5981 void | |
5982 job_info(job_T *job, dict_T *dict) | |
5983 { | |
5984 dictitem_T *item; | |
5985 varnumber_T nr; | |
5986 list_T *l; | |
5987 int i; | |
5988 | |
5989 dict_add_string(dict, "status", (char_u *)job_status(job)); | |
5990 | |
5991 item = dictitem_alloc((char_u *)"channel"); | |
5992 if (item == NULL) | |
5993 return; | |
5994 item->di_tv.v_type = VAR_CHANNEL; | |
5995 item->di_tv.vval.v_channel = job->jv_channel; | |
5996 if (job->jv_channel != NULL) | |
5997 ++job->jv_channel->ch_refcount; | |
5998 if (dict_add(dict, item) == FAIL) | |
5999 dictitem_free(item); | |
6000 | |
6001 #ifdef UNIX | |
6002 nr = job->jv_pid; | |
6003 #else | |
6004 nr = job->jv_proc_info.dwProcessId; | |
6005 #endif | |
6006 dict_add_number(dict, "process", nr); | |
6007 dict_add_string(dict, "tty_in", job->jv_tty_in); | |
6008 dict_add_string(dict, "tty_out", job->jv_tty_out); | |
6009 | |
6010 dict_add_number(dict, "exitval", job->jv_exitval); | |
6011 dict_add_string(dict, "exit_cb", job->jv_exit_cb.cb_name); | |
6012 dict_add_string(dict, "stoponexit", job->jv_stoponexit); | |
6013 #ifdef UNIX | |
6014 dict_add_string(dict, "termsig", job->jv_termsig); | |
6015 #endif | |
6016 #ifdef MSWIN | |
6017 dict_add_string(dict, "tty_type", job->jv_tty_type); | |
6018 #endif | |
6019 | |
6020 l = list_alloc(); | |
6021 if (l != NULL) | |
6022 { | |
6023 dict_add_list(dict, "cmd", l); | |
6024 if (job->jv_argv != NULL) | |
6025 for (i = 0; job->jv_argv[i] != NULL; i++) | |
6026 list_append_string(l, (char_u *)job->jv_argv[i], -1); | |
6027 } | |
6028 } | |
6029 | |
6030 /* | |
6031 * Implementation of job_info() to return info for all jobs. | |
6032 */ | |
6033 void | |
6034 job_info_all(list_T *l) | |
6035 { | |
6036 job_T *job; | |
6037 typval_T tv; | |
6038 | |
6039 for (job = first_job; job != NULL; job = job->jv_next) | |
6040 { | |
6041 tv.v_type = VAR_JOB; | |
6042 tv.vval.v_job = job; | |
6043 | |
6044 if (list_append_tv(l, &tv) != OK) | |
6045 return; | |
6046 } | |
6047 } | |
6048 | |
6049 /* | |
6050 * Send a signal to "job". Implements job_stop(). | 5979 * Send a signal to "job". Implements job_stop(). |
6051 * When "type" is not NULL use this for the type. | 5980 * When "type" is not NULL use this for the type. |
6052 * Otherwise use argvars[1] for the type. | 5981 * Otherwise use argvars[1] for the type. |
6053 */ | 5982 */ |
6054 int | 5983 int |
6145 &rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, NULL); | 6074 &rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, NULL); |
6146 clear_tv(&rettv); | 6075 clear_tv(&rettv); |
6147 return TRUE; | 6076 return TRUE; |
6148 } | 6077 } |
6149 | 6078 |
6079 /* | |
6080 * "prompt_setcallback({buffer}, {callback})" function | |
6081 */ | |
6082 void | |
6083 f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED) | |
6084 { | |
6085 buf_T *buf; | |
6086 callback_T callback; | |
6087 | |
6088 if (check_secure()) | |
6089 return; | |
6090 buf = tv_get_buf(&argvars[0], FALSE); | |
6091 if (buf == NULL) | |
6092 return; | |
6093 | |
6094 callback = get_callback(&argvars[1]); | |
6095 if (callback.cb_name == NULL) | |
6096 return; | |
6097 | |
6098 free_callback(&buf->b_prompt_callback); | |
6099 set_callback(&buf->b_prompt_callback, &callback); | |
6100 } | |
6101 | |
6102 /* | |
6103 * "prompt_setinterrupt({buffer}, {callback})" function | |
6104 */ | |
6105 void | |
6106 f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv UNUSED) | |
6107 { | |
6108 buf_T *buf; | |
6109 callback_T callback; | |
6110 | |
6111 if (check_secure()) | |
6112 return; | |
6113 buf = tv_get_buf(&argvars[0], FALSE); | |
6114 if (buf == NULL) | |
6115 return; | |
6116 | |
6117 callback = get_callback(&argvars[1]); | |
6118 if (callback.cb_name == NULL) | |
6119 return; | |
6120 | |
6121 free_callback(&buf->b_prompt_interrupt); | |
6122 set_callback(&buf->b_prompt_interrupt, &callback); | |
6123 } | |
6124 | |
6125 /* | |
6126 * "prompt_setprompt({buffer}, {text})" function | |
6127 */ | |
6128 void | |
6129 f_prompt_setprompt(typval_T *argvars, typval_T *rettv UNUSED) | |
6130 { | |
6131 buf_T *buf; | |
6132 char_u *text; | |
6133 | |
6134 if (check_secure()) | |
6135 return; | |
6136 buf = tv_get_buf(&argvars[0], FALSE); | |
6137 if (buf == NULL) | |
6138 return; | |
6139 | |
6140 text = tv_get_string(&argvars[1]); | |
6141 vim_free(buf->b_prompt_text); | |
6142 buf->b_prompt_text = vim_strsave(text); | |
6143 } | |
6144 | |
6145 /* | |
6146 * "ch_canread()" function | |
6147 */ | |
6148 void | |
6149 f_ch_canread(typval_T *argvars, typval_T *rettv) | |
6150 { | |
6151 channel_T *channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); | |
6152 | |
6153 rettv->vval.v_number = 0; | |
6154 if (channel != NULL) | |
6155 rettv->vval.v_number = channel_has_readahead(channel, PART_SOCK) | |
6156 || channel_has_readahead(channel, PART_OUT) | |
6157 || channel_has_readahead(channel, PART_ERR); | |
6158 } | |
6159 | |
6160 /* | |
6161 * "ch_close()" function | |
6162 */ | |
6163 void | |
6164 f_ch_close(typval_T *argvars, typval_T *rettv UNUSED) | |
6165 { | |
6166 channel_T *channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0); | |
6167 | |
6168 if (channel != NULL) | |
6169 { | |
6170 channel_close(channel, FALSE); | |
6171 channel_clear(channel); | |
6172 } | |
6173 } | |
6174 | |
6175 /* | |
6176 * "ch_close()" function | |
6177 */ | |
6178 void | |
6179 f_ch_close_in(typval_T *argvars, typval_T *rettv UNUSED) | |
6180 { | |
6181 channel_T *channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0); | |
6182 | |
6183 if (channel != NULL) | |
6184 channel_close_in(channel); | |
6185 } | |
6186 | |
6187 /* | |
6188 * "ch_getbufnr()" function | |
6189 */ | |
6190 void | |
6191 f_ch_getbufnr(typval_T *argvars, typval_T *rettv) | |
6192 { | |
6193 channel_T *channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); | |
6194 | |
6195 rettv->vval.v_number = -1; | |
6196 if (channel != NULL) | |
6197 { | |
6198 char_u *what = tv_get_string(&argvars[1]); | |
6199 int part; | |
6200 | |
6201 if (STRCMP(what, "err") == 0) | |
6202 part = PART_ERR; | |
6203 else if (STRCMP(what, "out") == 0) | |
6204 part = PART_OUT; | |
6205 else if (STRCMP(what, "in") == 0) | |
6206 part = PART_IN; | |
6207 else | |
6208 part = PART_SOCK; | |
6209 if (channel->ch_part[part].ch_bufref.br_buf != NULL) | |
6210 rettv->vval.v_number = | |
6211 channel->ch_part[part].ch_bufref.br_buf->b_fnum; | |
6212 } | |
6213 } | |
6214 | |
6215 /* | |
6216 * "ch_getjob()" function | |
6217 */ | |
6218 void | |
6219 f_ch_getjob(typval_T *argvars, typval_T *rettv) | |
6220 { | |
6221 channel_T *channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); | |
6222 | |
6223 if (channel != NULL) | |
6224 { | |
6225 rettv->v_type = VAR_JOB; | |
6226 rettv->vval.v_job = channel->ch_job; | |
6227 if (channel->ch_job != NULL) | |
6228 ++channel->ch_job->jv_refcount; | |
6229 } | |
6230 } | |
6231 | |
6232 /* | |
6233 * "ch_info()" function | |
6234 */ | |
6235 void | |
6236 f_ch_info(typval_T *argvars, typval_T *rettv UNUSED) | |
6237 { | |
6238 channel_T *channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); | |
6239 | |
6240 if (channel != NULL && rettv_dict_alloc(rettv) != FAIL) | |
6241 channel_info(channel, rettv->vval.v_dict); | |
6242 } | |
6243 | |
6244 /* | |
6245 * "ch_log()" function | |
6246 */ | |
6247 void | |
6248 f_ch_log(typval_T *argvars, typval_T *rettv UNUSED) | |
6249 { | |
6250 char_u *msg = tv_get_string(&argvars[0]); | |
6251 channel_T *channel = NULL; | |
6252 | |
6253 if (argvars[1].v_type != VAR_UNKNOWN) | |
6254 channel = get_channel_arg(&argvars[1], FALSE, FALSE, 0); | |
6255 | |
6256 ch_log(channel, "%s", msg); | |
6257 } | |
6258 | |
6259 /* | |
6260 * "ch_logfile()" function | |
6261 */ | |
6262 void | |
6263 f_ch_logfile(typval_T *argvars, typval_T *rettv UNUSED) | |
6264 { | |
6265 char_u *fname; | |
6266 char_u *opt = (char_u *)""; | |
6267 char_u buf[NUMBUFLEN]; | |
6268 | |
6269 /* Don't open a file in restricted mode. */ | |
6270 if (check_restricted() || check_secure()) | |
6271 return; | |
6272 fname = tv_get_string(&argvars[0]); | |
6273 if (argvars[1].v_type == VAR_STRING) | |
6274 opt = tv_get_string_buf(&argvars[1], buf); | |
6275 ch_logfile(fname, opt); | |
6276 } | |
6277 | |
6278 /* | |
6279 * "ch_open()" function | |
6280 */ | |
6281 void | |
6282 f_ch_open(typval_T *argvars, typval_T *rettv) | |
6283 { | |
6284 rettv->v_type = VAR_CHANNEL; | |
6285 if (check_restricted() || check_secure()) | |
6286 return; | |
6287 rettv->vval.v_channel = channel_open_func(argvars); | |
6288 } | |
6289 | |
6290 /* | |
6291 * "ch_read()" function | |
6292 */ | |
6293 void | |
6294 f_ch_read(typval_T *argvars, typval_T *rettv) | |
6295 { | |
6296 common_channel_read(argvars, rettv, FALSE, FALSE); | |
6297 } | |
6298 | |
6299 /* | |
6300 * "ch_readblob()" function | |
6301 */ | |
6302 void | |
6303 f_ch_readblob(typval_T *argvars, typval_T *rettv) | |
6304 { | |
6305 common_channel_read(argvars, rettv, TRUE, TRUE); | |
6306 } | |
6307 | |
6308 /* | |
6309 * "ch_readraw()" function | |
6310 */ | |
6311 void | |
6312 f_ch_readraw(typval_T *argvars, typval_T *rettv) | |
6313 { | |
6314 common_channel_read(argvars, rettv, TRUE, FALSE); | |
6315 } | |
6316 | |
6317 /* | |
6318 * "ch_evalexpr()" function | |
6319 */ | |
6320 void | |
6321 f_ch_evalexpr(typval_T *argvars, typval_T *rettv) | |
6322 { | |
6323 ch_expr_common(argvars, rettv, TRUE); | |
6324 } | |
6325 | |
6326 /* | |
6327 * "ch_sendexpr()" function | |
6328 */ | |
6329 void | |
6330 f_ch_sendexpr(typval_T *argvars, typval_T *rettv) | |
6331 { | |
6332 ch_expr_common(argvars, rettv, FALSE); | |
6333 } | |
6334 | |
6335 /* | |
6336 * "ch_evalraw()" function | |
6337 */ | |
6338 void | |
6339 f_ch_evalraw(typval_T *argvars, typval_T *rettv) | |
6340 { | |
6341 ch_raw_common(argvars, rettv, TRUE); | |
6342 } | |
6343 | |
6344 /* | |
6345 * "ch_sendraw()" function | |
6346 */ | |
6347 void | |
6348 f_ch_sendraw(typval_T *argvars, typval_T *rettv) | |
6349 { | |
6350 ch_raw_common(argvars, rettv, FALSE); | |
6351 } | |
6352 | |
6353 /* | |
6354 * "ch_setoptions()" function | |
6355 */ | |
6356 void | |
6357 f_ch_setoptions(typval_T *argvars, typval_T *rettv UNUSED) | |
6358 { | |
6359 channel_T *channel; | |
6360 jobopt_T opt; | |
6361 | |
6362 channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); | |
6363 if (channel == NULL) | |
6364 return; | |
6365 clear_job_options(&opt); | |
6366 if (get_job_options(&argvars[1], &opt, | |
6367 JO_CB_ALL + JO_TIMEOUT_ALL + JO_MODE_ALL, 0) == OK) | |
6368 channel_set_options(channel, &opt); | |
6369 free_job_options(&opt); | |
6370 } | |
6371 | |
6372 /* | |
6373 * "ch_status()" function | |
6374 */ | |
6375 void | |
6376 f_ch_status(typval_T *argvars, typval_T *rettv) | |
6377 { | |
6378 channel_T *channel; | |
6379 jobopt_T opt; | |
6380 int part = -1; | |
6381 | |
6382 /* return an empty string by default */ | |
6383 rettv->v_type = VAR_STRING; | |
6384 rettv->vval.v_string = NULL; | |
6385 | |
6386 channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); | |
6387 | |
6388 if (argvars[1].v_type != VAR_UNKNOWN) | |
6389 { | |
6390 clear_job_options(&opt); | |
6391 if (get_job_options(&argvars[1], &opt, JO_PART, 0) == OK | |
6392 && (opt.jo_set & JO_PART)) | |
6393 part = opt.jo_part; | |
6394 } | |
6395 | |
6396 rettv->vval.v_string = vim_strsave((char_u *)channel_status(channel, part)); | |
6397 } | |
6398 | |
6399 /* | |
6400 * Get the job from the argument. | |
6401 * Returns NULL if the job is invalid. | |
6402 */ | |
6403 static job_T * | |
6404 get_job_arg(typval_T *tv) | |
6405 { | |
6406 job_T *job; | |
6407 | |
6408 if (tv->v_type != VAR_JOB) | |
6409 { | |
6410 semsg(_(e_invarg2), tv_get_string(tv)); | |
6411 return NULL; | |
6412 } | |
6413 job = tv->vval.v_job; | |
6414 | |
6415 if (job == NULL) | |
6416 emsg(_("E916: not a valid job")); | |
6417 return job; | |
6418 } | |
6419 | |
6420 /* | |
6421 * "job_getchannel()" function | |
6422 */ | |
6423 void | |
6424 f_job_getchannel(typval_T *argvars, typval_T *rettv) | |
6425 { | |
6426 job_T *job = get_job_arg(&argvars[0]); | |
6427 | |
6428 if (job != NULL) | |
6429 { | |
6430 rettv->v_type = VAR_CHANNEL; | |
6431 rettv->vval.v_channel = job->jv_channel; | |
6432 if (job->jv_channel != NULL) | |
6433 ++job->jv_channel->ch_refcount; | |
6434 } | |
6435 } | |
6436 | |
6437 /* | |
6438 * Implementation of job_info(). | |
6439 */ | |
6440 static void | |
6441 job_info(job_T *job, dict_T *dict) | |
6442 { | |
6443 dictitem_T *item; | |
6444 varnumber_T nr; | |
6445 list_T *l; | |
6446 int i; | |
6447 | |
6448 dict_add_string(dict, "status", (char_u *)job_status(job)); | |
6449 | |
6450 item = dictitem_alloc((char_u *)"channel"); | |
6451 if (item == NULL) | |
6452 return; | |
6453 item->di_tv.v_type = VAR_CHANNEL; | |
6454 item->di_tv.vval.v_channel = job->jv_channel; | |
6455 if (job->jv_channel != NULL) | |
6456 ++job->jv_channel->ch_refcount; | |
6457 if (dict_add(dict, item) == FAIL) | |
6458 dictitem_free(item); | |
6459 | |
6460 #ifdef UNIX | |
6461 nr = job->jv_pid; | |
6462 #else | |
6463 nr = job->jv_proc_info.dwProcessId; | |
6464 #endif | |
6465 dict_add_number(dict, "process", nr); | |
6466 dict_add_string(dict, "tty_in", job->jv_tty_in); | |
6467 dict_add_string(dict, "tty_out", job->jv_tty_out); | |
6468 | |
6469 dict_add_number(dict, "exitval", job->jv_exitval); | |
6470 dict_add_string(dict, "exit_cb", job->jv_exit_cb.cb_name); | |
6471 dict_add_string(dict, "stoponexit", job->jv_stoponexit); | |
6472 #ifdef UNIX | |
6473 dict_add_string(dict, "termsig", job->jv_termsig); | |
6474 #endif | |
6475 #ifdef MSWIN | |
6476 dict_add_string(dict, "tty_type", job->jv_tty_type); | |
6477 #endif | |
6478 | |
6479 l = list_alloc(); | |
6480 if (l != NULL) | |
6481 { | |
6482 dict_add_list(dict, "cmd", l); | |
6483 if (job->jv_argv != NULL) | |
6484 for (i = 0; job->jv_argv[i] != NULL; i++) | |
6485 list_append_string(l, (char_u *)job->jv_argv[i], -1); | |
6486 } | |
6487 } | |
6488 | |
6489 /* | |
6490 * Implementation of job_info() to return info for all jobs. | |
6491 */ | |
6492 static void | |
6493 job_info_all(list_T *l) | |
6494 { | |
6495 job_T *job; | |
6496 typval_T tv; | |
6497 | |
6498 for (job = first_job; job != NULL; job = job->jv_next) | |
6499 { | |
6500 tv.v_type = VAR_JOB; | |
6501 tv.vval.v_job = job; | |
6502 | |
6503 if (list_append_tv(l, &tv) != OK) | |
6504 return; | |
6505 } | |
6506 } | |
6507 | |
6508 /* | |
6509 * "job_info()" function | |
6510 */ | |
6511 void | |
6512 f_job_info(typval_T *argvars, typval_T *rettv) | |
6513 { | |
6514 if (argvars[0].v_type != VAR_UNKNOWN) | |
6515 { | |
6516 job_T *job = get_job_arg(&argvars[0]); | |
6517 | |
6518 if (job != NULL && rettv_dict_alloc(rettv) != FAIL) | |
6519 job_info(job, rettv->vval.v_dict); | |
6520 } | |
6521 else if (rettv_list_alloc(rettv) == OK) | |
6522 job_info_all(rettv->vval.v_list); | |
6523 } | |
6524 | |
6525 /* | |
6526 * "job_setoptions()" function | |
6527 */ | |
6528 void | |
6529 f_job_setoptions(typval_T *argvars, typval_T *rettv UNUSED) | |
6530 { | |
6531 job_T *job = get_job_arg(&argvars[0]); | |
6532 jobopt_T opt; | |
6533 | |
6534 if (job == NULL) | |
6535 return; | |
6536 clear_job_options(&opt); | |
6537 if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT + JO_EXIT_CB, 0) == OK) | |
6538 job_set_options(job, &opt); | |
6539 free_job_options(&opt); | |
6540 } | |
6541 | |
6542 /* | |
6543 * "job_start()" function | |
6544 */ | |
6545 void | |
6546 f_job_start(typval_T *argvars, typval_T *rettv) | |
6547 { | |
6548 rettv->v_type = VAR_JOB; | |
6549 if (check_restricted() || check_secure()) | |
6550 return; | |
6551 rettv->vval.v_job = job_start(argvars, NULL, NULL, FALSE); | |
6552 } | |
6553 | |
6554 /* | |
6555 * "job_status()" function | |
6556 */ | |
6557 void | |
6558 f_job_status(typval_T *argvars, typval_T *rettv) | |
6559 { | |
6560 job_T *job = get_job_arg(&argvars[0]); | |
6561 | |
6562 if (job != NULL) | |
6563 { | |
6564 rettv->v_type = VAR_STRING; | |
6565 rettv->vval.v_string = vim_strsave((char_u *)job_status(job)); | |
6566 } | |
6567 } | |
6568 | |
6569 /* | |
6570 * "job_stop()" function | |
6571 */ | |
6572 void | |
6573 f_job_stop(typval_T *argvars, typval_T *rettv) | |
6574 { | |
6575 job_T *job = get_job_arg(&argvars[0]); | |
6576 | |
6577 if (job != NULL) | |
6578 rettv->vval.v_number = job_stop(job, argvars, NULL); | |
6579 } | |
6580 | |
6150 #endif /* FEAT_JOB_CHANNEL */ | 6581 #endif /* FEAT_JOB_CHANNEL */ |