erl_call.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 904 行 · 第 1/2 页

C
904
字号
/* ``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$ *//* * Function: Makes it possible to send and receive Erlang *    messages from the (Unix) command line.  *    Note: We don't free any memory at all since we only *    live for a short while.    * */#ifdef __WIN32__#include <winsock2.h>#include <direct.h>#include <windows.h>#include <winbase.h>#elif VXWORKS#include <stdio.h>#include <string.h>#include <vxWorks.h>#include <hostLib.h>#include <selectLib.h>#include <ifLib.h>#include <sockLib.h>#include <taskLib.h>#include <inetLib.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/tcp.h> #include <time.h>#else /* unix */#include <sys/types.h>#include <sys/uio.h>#include <sys/time.h>#include <unistd.h>#include <sys/param.h> #include <netdb.h>#include <sys/times.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <signal.h>#include "ei.h"#include "ei_resolve.h"#include "erl_start.h"		/* FIXME remove dependency */#ifdef __WIN32__static void initWinSock(void);#endif/* * Some nice global variables * (I don't think "nice" is the right word actually... -gordon) *//* FIXME problem for threaded ? */struct call_flags {    int startp;    int cookiep;    int modp;    int evalp;    int randomp;    int use_long_name;	/* indicates if -name was used, else -sname or -n */    int debugp;    int verbosep;    int haltp;    char *cookie;    char *node;    char *hidden;    char *apply;    char *script;};static void usage_arg(const char *progname, const char *switchname);static void usage_error(const char *progname, const char *switchname);static void usage(const char *progname);static int get_module(char **mbuf, char **mname);static struct hostent* get_hostent(char *host);static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags);static int read_stdin(char **buf);static void split_apply_string(char *str, char **mod, 			       char **fun, char **args);/*************************************************************************** * *  XXXXX * ***************************************************************************//* FIXME isn't VxWorks to handle arguments differently? *//* FIXME check errors from malloc */#if !defined(VXWORKS)int main(int argc, char *argv[])#elseint erl_call(int argc, char **argv)#endif{    int i = 1,fd,creation;    struct hostent *hp;    char host_name[EI_MAXHOSTNAMELEN+1];    char nodename[MAXNODELEN+1];    char *p = NULL;    char *ct = NULL; /* temporary used when truncating nodename */    int modsize = 0;    char *host = NULL;    char *module = NULL;    char *modname = NULL;    struct call_flags flags = {0}; /* Default 0 and NULL in all fields */    char* progname = argv[0];    ei_cnode ec;    /* Get the command line options */    while (i < argc) {	if (argv[i][0] != '-') {	    usage_error(progname, argv[i]);	}	if (strcmp(argv[i], "-sname") == 0) { /* -sname NAME */	    if (i+1 >= argc) {		usage_arg(progname, "-sname ");	    }	    flags.node = (char *) malloc(strlen(argv[i+1]) + 1);	    strcpy(flags.node, argv[i+1]);	    i++;	    flags.use_long_name = 0;	} else if (strcmp(argv[i], "-name") == 0) {  /* -name NAME */	    if (i+1 >= argc) {		usage_arg(progname, "-name ");	    }	    flags.node = (char *) malloc(strlen(argv[i+1]) + 1);	    strcpy(flags.node, argv[i+1]);	    i++;	    flags.use_long_name = 1;	} else {	    if (strlen(argv[i]) != 2) {		usage_error(progname, argv[i]);	    }		    	    switch (argv[i][1]) {	    case 's':		flags.startp = 1;		break;	    case 'q':		flags.haltp = 1;		break;	    case 'v':		flags.verbosep = 1;		break;	    case 'd':		flags.debugp = 1;		break;	    case 'r':		flags.randomp = 1;		break;	    case 'e':		flags.evalp = 1;		break;	    case 'm':		flags.modp = 1;		break;	    case 'c':		if (i+1 >= argc) {		    usage_arg(progname, "-c ");		}		flags.cookiep = 1;		flags.cookie = (char *) malloc(strlen(argv[i+1]) + 1);		strcpy(flags.cookie, argv[i+1]);		i++;		break;	    case 'n':		if (i+1 >= argc) {		    usage_arg(progname, "-n ");		}		flags.node = (char *) malloc(strlen(argv[i+1]) + 1);		strcpy(flags.node, argv[i+1]);		flags.use_long_name = 1;		i++;		break;	    case 'h':		if (i+1 >= argc) {		    usage_arg(progname, "-h ");		}		flags.hidden = (char *) malloc(strlen(argv[i+1]) + 1);		strcpy(flags.hidden, argv[i+1]);		i++;		break;	    case 'x':		if (i+1 >= argc) {		    usage_arg(progname, "-x ");		}		flags.script = (char *) malloc(strlen(argv[i+1]) + 1);		strcpy(flags.script, argv[i+1]);		i++;		break;	    case 'a':		if (i+1 >= argc) {		    usage_arg(progname, "-a ");		}		flags.apply = (char *) malloc(strlen(argv[i+1]) + 1);		strcpy(flags.apply, argv[i+1]);		i++;		break;	    case '?':		usage(progname);	    default:		usage_error(progname, argv[i]);	    }	}	i++;    } /* while */	    /*     * Can't have them both !     */    if (flags.modp && flags.evalp) {      usage(progname);    }    /*     * Read an Erlang module from stdin.     */    if (flags.modp) {      modsize = get_module(&module, &modname);    }    if (flags.verbosep || flags.debugp) {	fprintf(stderr,"erl_call: "		"node = %s\nCookie = %s\n"		"flags = %s %s %s\n"		"module: name = %s , size = %d\n"		"apply = %s\n",		(flags.node ? flags.node : ""),		(flags.cookie ? flags.cookie : ""),		(flags.startp ? "startp" : ""),		(flags.verbosep ? "verbosep" : ""),		(flags.debugp ? "debugp" : ""),		(modname ? modname : ""), modsize,		(flags.apply ? flags.apply : "" ));    }    /*      * What we, at least, requires !     */    if (flags.node == NULL) {	usage(progname);    }    if (!flags.cookiep) {	flags.cookie = NULL;    }    /* FIXME decide how many bits etc or leave to connect_xinit? */    creation = (time(NULL) % 3) + 1; /* "random" */    if (flags.hidden == NULL) {      /* As default we are c17@gethostname */      i = flags.randomp ? (time(NULL) % 997) : 17;      /* FIXME allocates to small !!! */      flags.hidden = (char *) malloc(3 + 2 ); /* c17 or cXYZ */#if defined(VXWORKS)      sprintf(flags.hidden, "c%d",	  i < 0 ?  (int) taskIdSelf() : i);#else      sprintf(flags.hidden, "c%d",	  i < 0 ?  (int) getpid() : i);#endif    }    {      /* A name for our hidden node was specified */      char h_hostname[EI_MAXHOSTNAMELEN+1];      char h_nodename[MAXNODELEN+1];      char *h_alivename=flags.hidden;      struct in_addr h_ipadr;      char* ct;#ifdef __WIN32__      /*       * FIXME Extremly ugly, but needed to get ei_gethostbyname() below       * to work.       */      initWinSock();#endif      gethostname(h_hostname, EI_MAXHOSTNAMELEN);      if ((hp = ei_gethostbyname(h_hostname)) == 0) {	  fprintf(stderr,"erl_call: can't resolve hostname %s\n", h_hostname);	  exit(1);      }      /* If shortnames cut of the name at first '.' */      if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {	  *ct = '\0';      }      strcpy(h_hostname, hp->h_name);      memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr));      sprintf(h_nodename, "%s@%s", h_alivename, h_hostname);            if (ei_connect_xinit(&ec, h_hostname, h_alivename, h_nodename,			   (Erl_IpAddr)&h_ipadr, flags.cookie, 			   (short) creation) < 0) {	  fprintf(stderr,"erl_call: can't create C node %s; %d\n",		  h_nodename, erl_errno);      	  exit(1);      }    }    if ((p = strchr((const char *)flags.node, (int) '@')) == 0) {	strcpy(host_name, ei_thishostname(&ec));	host = host_name;    } else {	*p = 0;	host = p+1;    }    /*      * Expand name to a real name (may be ip-address)      */    /* FIXME better error string */    if ((hp = get_hostent(host)) == 0) {	fprintf(stderr,"erl_call: can't get_hostent(%s)\n", host);	exit(1);    }    /* If shortnames cut of the name at first '.' */    if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {	*ct = '\0';    }    strcpy(host_name, hp->h_name);    sprintf(nodename, "%s@%s", flags.node, host_name);    /*      * Try to connect. Start an Erlang system if the     * start option is on and no system is running.     */    if (flags.startp && !flags.haltp) {	fd = do_connect(&ec, nodename, &flags);    } else if ((fd = ei_connect(&ec, nodename)) < 0) {	/* We failed to connect ourself */	/* FIXME do we really know we failed because of node not up? */	if (flags.haltp) {	    exit(0);	} else {	    fprintf(stderr,"erl_call: failed to connect to node %s\n",		    nodename);	    exit(1);	}    }    /* If we are connected and the halt switch is set */    if (fd && flags.haltp) {	int i = 0;	char *p;	ei_x_buff reply;	ei_encode_empty_list(NULL, &i);	p = (char *)malloc(i);	i = 0;		/* Reset */	  	ei_encode_empty_list(p, &i);	ei_x_new_with_version(&reply);	/* FIXME if fails we want to exit != 0 ? */	ei_rpc(&ec, fd, "erlang", "halt", p, i, &reply);	free(p);	ei_x_free(&reply);	exit(0);    }    if (flags.verbosep) {	fprintf(stderr,"erl_call: we are now connected to node \"%s\"\n",		nodename);    }    /*     * Compile the module read from stdin.     */    if (flags.modp && (modname != NULL)) {      char fname[256];      strcpy(fname, modname);      strcat(fname, ".erl");      /*       * ei_format("[~s,~w]", fname, erl_mk_binary(module, modsize));       */      {	  int i = 0;	  char *p;	  ei_x_buff reply;	  ei_encode_list_header(NULL, &i, 2);	  ei_encode_string(NULL, &i, fname);	  ei_encode_binary(NULL, &i, module, modsize);	  ei_encode_empty_list(NULL, &i);	  p = (char *)malloc(i);	  i = 0;		/* Reset */	  	  ei_encode_list_header(p, &i, 2);	  ei_encode_string(p, &i, fname);	  ei_encode_binary(p, &i, module, modsize);	  ei_encode_empty_list(p, &i);	  ei_x_new_with_version(&reply);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?