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 + -
显示快捷键?