📄 erl_bif_port.c
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ */#ifdef HAVE_CONFIG_H# include "config.h"#endif#ifdef _OSE_# include "ose.h"#endif#include "sys.h"#include "erl_vm.h"#include "erl_sys_driver.h"#include "global.h"#include "erl_process.h"#include "error.h"#include "bif.h"#include "big.h"#include "dist.h"#include "erl_version.h"#include "erl_binary.h"#include "erl_db_util.h"#include "register.h"#include "external.h"extern ErlDrvEntry fd_driver_entry;extern ErlDrvEntry vanilla_driver_entry;extern ErlDrvEntry spawn_driver_entry;static int open_port(Process* p, Eterm name, Eterm settings, int *err_nump);static byte* convert_environment(Process* p, Eterm env);BIF_RETTYPE open_port_2(BIF_ALIST_2){ int port_num; Eterm port_val; char *str; int err_num; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); if ((port_num = open_port(BIF_P, BIF_ARG_1, BIF_ARG_2, &err_num)) < 0) { erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); if (port_num == -3) { BIF_ERROR(BIF_P, BADARG); } if (port_num == -2) str = erl_errno_id(err_num); else str = "einval"; BIF_P->fvalue = am_atom_put(str, strlen(str)); BIF_ERROR(BIF_P, EXC_ERROR); } erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN|ERTS_PROC_LOCK_LINK); port_val = erts_port[port_num].id; erts_add_link(&(erts_port[port_num].nlinks), LINK_PID, BIF_P->id); erts_add_link(&(BIF_P->nlinks), LINK_PID, port_val); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK); erts_port_release(&erts_port[port_num]); BIF_RET(port_val);}/**************************************************************************** PORT BIFS: port_command/2 -- replace Port ! {..., {command, Data}} port_command(Port, Data) -> true when port(Port), io-list(Data) port_control/3 -- new port_control(Port, Ctl, Data) -> Reply port_control(Port, Ctl, Data) -> Reply where integer(Ctl), io-list(Data), io-list(Reply) port_close/1 -- replace Port ! {..., close} port_close(Port) -> true when port(Port) port_connect/2 -- replace Port ! {..., {connect, Pid}} port_connect(Port, Pid) when port(Port), pid(Pid) ***************************************************************************/static Port*id_or_name2port(Process *c_p, Eterm id){ Port *port; if (is_not_atom(id)) port = erts_id2port(id, c_p, ERTS_PROC_LOCK_MAIN); else erts_whereis_name(c_p, ERTS_PROC_LOCK_MAIN, id, NULL, 0, 0, &port); return port;}BIF_RETTYPE port_command_2(BIF_ALIST_2){ BIF_RETTYPE res; Port *p; p = id_or_name2port(BIF_P, BIF_ARG_1); if (!p) { BIF_ERROR(BIF_P, BADARG); } ERTS_BIF_PREP_RET(res, am_true); if (p->status & ERTS_PORT_SFLG_PORT_BUSY) { erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, p); if (erts_system_monitor_flags.busy_port) { monitor_generic(BIF_P, am_busy_port, p->id); } ERTS_BIF_PREP_ERROR(res, BIF_P, RESCHEDULE); } else { int wres; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); ERTS_SMP_CHK_NO_PROC_LOCKS; wres = erts_write_to_port(BIF_P->id, p, BIF_ARG_2); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); if (wres != 0) { ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG); } } erts_port_release(p); if (ERTS_PROC_IS_EXITING(BIF_P)) { KILL_CATCHES(BIF_P); /* Must exit */ ERTS_BIF_PREP_ERROR(res, BIF_P, EXC_ERROR); } return res;}static byte *erts_port_call_buff;static Uint erts_port_call_buff_size;/* Reversed logic to make VxWorks happy */static int erts_port_call_need_init = 1; static byte *ensure_buff(Uint size){ if (erts_port_call_need_init) { erts_port_call_buff = erts_alloc(ERTS_ALC_T_PORT_CALL_BUF, (size_t) size); erts_port_call_buff_size = size; erts_port_call_need_init = 0; } else if (erts_port_call_buff_size < size) { erts_port_call_buff_size = size; erts_port_call_buff = erts_realloc(ERTS_ALC_T_PORT_CALL_BUF, (void *) erts_port_call_buff, (size_t) size); } return erts_port_call_buff;}BIF_RETTYPE port_call_2(BIF_ALIST_2){ return port_call_3(BIF_P,BIF_ARG_1,make_small(0),BIF_ARG_2);}BIF_RETTYPE port_call_3(BIF_ALIST_3){ Uint op; Port *p; Uint size; byte *bytes; byte *endp; size_t real_size; ErlDrvEntry *drv; byte port_result[128]; /* Buffer for result from port. */ byte* port_resp; /* Pointer to result buffer. */ char *prc; int ret; Eterm res; int result_size; Eterm *hp; Eterm *hp_end; /* To satisfy hybrid heap architecture */ unsigned ret_flags = 0U; port_resp = port_result; p = id_or_name2port(BIF_P, BIF_ARG_1); if (!p) { error: if (port_resp != port_result && !(ret_flags & DRIVER_CALL_KEEP_BUFFER)) { driver_free(port_resp); } if (p) erts_port_release(p);#ifdef ERTS_SMP ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN);#else ERTS_BIF_CHK_EXITED(BIF_P);#endif BIF_ERROR(BIF_P, BADARG); } if ((drv = p->drv_ptr) == NULL) { goto error; } if (drv->call == NULL) { goto error; } if (!term_to_Uint(BIF_ARG_2, &op)) { goto error; } size = encode_size_struct(BIF_ARG_3, TERM_TO_BINARY_DFLAGS); bytes = ensure_buff(size); endp = bytes; if (erts_to_external_format(NULL, BIF_ARG_3, &endp, NULL, NULL) || !endp) { erl_exit(1, "%s, line %d: bad term: %x\n", __FILE__, __LINE__, BIF_ARG_3); } real_size = endp - bytes; if (real_size > size) { erl_exit(1, "%s, line %d: buffer overflow: %d word(s)\n", __FILE__, __LINE__, endp - (bytes + size)); } p->caller = BIF_P->id; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); prc = (char *) port_resp; ret = drv->call((ErlDrvData)p->drv_data, (unsigned) op, (char *) bytes, (int) real_size, &prc, (int) sizeof(port_result), &ret_flags); port_resp = (byte *) prc; p->caller = NIL; erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);#ifdef HARDDEBUG { int z; printf("real_size = %ld,%d, ret = %d\r\n",real_size, (int) real_size, ret); printf("["); for(z = 0; z < real_size; ++z) { printf("%d, ",(int) bytes[z]); } printf("]\r\n"); printf("["); for(z = 0; z < ret; ++z) { printf("%d, ",(int) port_resp[z]); } printf("]\r\n"); }#endif if (ret <= 0 || port_resp[0] != VERSION_MAGIC) { /* Error or a binary without magic/ with wrong magic */ goto error; } result_size = decode_size(port_resp, ret); if (result_size < 0) { goto error; } hp = HAlloc(BIF_P, result_size); hp_end = hp + result_size; endp = port_resp; if ((res = erts_from_external_format(NULL, &hp, &endp, &MSO(BIF_P))) == THE_NON_VALUE) { goto error; } HRelease(BIF_P, hp_end, hp); if (port_resp != port_result && !(ret_flags & DRIVER_CALL_KEEP_BUFFER)) { driver_free(port_resp); } if (p) erts_port_release(p);#ifdef ERTS_SMP ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN);#else ERTS_BIF_CHK_EXITED(BIF_P);#endif return res;} BIF_RETTYPE port_control_3(BIF_ALIST_3){ Port* p; Uint op; Eterm res = THE_NON_VALUE; p = id_or_name2port(BIF_P, BIF_ARG_1); if (!p) { BIF_ERROR(BIF_P, BADARG); } if (term_to_Uint(BIF_ARG_2, &op)) res = erts_port_control(BIF_P, p, op, BIF_ARG_3); erts_port_release(p);#ifdef ERTS_SMP ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN);#else ERTS_BIF_CHK_EXITED(BIF_P);#endif if (is_non_value(res)) { BIF_ERROR(BIF_P, BADARG); } BIF_RET(res);}BIF_RETTYPE port_close_1(BIF_ALIST_1){ Port* p; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); p = id_or_name2port(NULL, BIF_ARG_1); if (!p) { erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); BIF_ERROR(BIF_P, BADARG); } erts_do_exit_port(p, p->connected, am_normal); /* if !ERTS_SMP: since we terminate port with reason normal we SHOULD never get an exit signal ourselves */ erts_port_release(p); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); BIF_RET(am_true);}BIF_RETTYPE port_connect_2(BIF_ALIST_2){ Port* prt; Process* rp; Eterm pid = BIF_ARG_2; if (is_not_internal_pid(pid)) { error: BIF_ERROR(BIF_P, BADARG); } prt = id_or_name2port(BIF_P, BIF_ARG_1); if (!prt) { goto error; } rp = erts_pid2proc(BIF_P, ERTS_PROC_LOCK_MAIN, pid, ERTS_PROC_LOCK_LINK); if (!rp) { erts_smp_port_unlock(prt); ERTS_SMP_ASSERT_IS_NOT_EXITING(BIF_P); goto error; } erts_add_link(&(rp->nlinks), LINK_PID, prt->id); erts_add_link(&(prt->nlinks), LINK_PID, pid); erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_LINK); prt->connected = pid; /* internal pid */ erts_smp_port_unlock(prt); BIF_RET(am_true);}BIF_RETTYPE port_set_data_2(BIF_ALIST_2){ Port* prt; Eterm portid = BIF_ARG_1; Eterm data = BIF_ARG_2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -