⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_bif_port.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ``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 + -