1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 1996-2020. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 *
20
21 */
22 /*
23 * Function: Makes it possible to send and receive Erlang
24 * messages from the (Unix) command line.
25 * Note: We don't free any memory at all since we only
26 * live for a short while.
27 *
28 */
29
30 #ifdef __WIN32__
31 #include <winsock2.h>
32 #include <direct.h>
33 #include <windows.h>
34 #include <winbase.h>
35
36 #elif VXWORKS
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <vxWorks.h>
41 #include <hostLib.h>
42 #include <selectLib.h>
43 #include <ifLib.h>
44 #include <sockLib.h>
45 #include <taskLib.h>
46 #include <inetLib.h>
47 #include <unistd.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <netinet/tcp.h>
51 #include <time.h>
52
53 #else /* unix */
54
55 #include <sys/types.h>
56 #include <sys/uio.h>
57 #include <sys/time.h>
58 #include <unistd.h>
59 #include <sys/param.h>
60 #include <netdb.h>
61 #include <sys/times.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65
66 #if TIME_WITH_SYS_TIME
67 # include <sys/time.h>
68 # include <time.h>
69 #else
70 # if HAVE_SYS_TIME_H
71 # include <sys/time.h>
72 # else
73 # include <time.h>
74 # endif
75 #endif
76
77 #endif
78
79 #include <stdio.h>
80 #include <stdlib.h>
81
82 #include <string.h>
83 #include <ctype.h>
84 #include <fcntl.h>
85 #include <signal.h>
86
87 #include "ei.h"
88 #include "ei_resolve.h"
89 #include "erl_start.h" /* FIXME remove dependency */
90
91 /*
92 * Some nice global variables
93 * (I don't think "nice" is the right word actually... -gordon)
94 */
95 /* FIXME problem for threaded ? */
96
97 struct call_flags {
98 int startp;
99 int cookiep;
100 int modp;
101 int evalp;
102 int randomp;
103 int use_long_name; /* indicates if -name was used, else -sname or -n */
104 int debugp;
105 int verbosep;
106 int haltp;
107 char *cookie;
108 char *node;
109 char *hidden;
110 char *apply;
111 char *script;
112 };
113
114 static void usage_arg(const char *progname, const char *switchname);
115 static void usage_error(const char *progname, const char *switchname);
116 static void usage(const char *progname);
117 static int get_module(char **mbuf, char **mname);
118 static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags);
119 static int read_stdin(char **buf);
120 static void split_apply_string(char *str, char **mod,
121 char **fun, char **args);
122 static void* ei_chk_malloc(size_t size);
123 static void* ei_chk_calloc(size_t nmemb, size_t size);
124 static void* ei_chk_realloc(void *old, size_t size);
125 static char* ei_chk_strdup(char *s);
126
127
128 /***************************************************************************
129 *
130 * XXXXX
131 *
132 ***************************************************************************/
133
134 /* FIXME isn't VxWorks to handle arguments differently? */
135
136 #if !defined(VXWORKS)
main(int argc,char * argv[])137 int main(int argc, char *argv[])
138 #else
139 int erl_call(int argc, char **argv)
140 #endif
141 {
142 int i = 1,fd,creation;
143 struct hostent *hp;
144 char host_name[EI_MAXHOSTNAMELEN+1];
145 char nodename[MAXNODELEN+1];
146 char *p = NULL;
147 char *ct = NULL; /* temporary used when truncating nodename */
148 int modsize = 0;
149 char *host = NULL;
150 char *module = NULL;
151 char *modname = NULL;
152 struct call_flags flags = {0}; /* Default 0 and NULL in all fields */
153 char* progname = argv[0];
154 ei_cnode ec;
155
156 ei_init();
157
158 /* Get the command line options */
159 while (i < argc) {
160 if (argv[i][0] != '-') {
161 usage_error(progname, argv[i]);
162 }
163
164 if (strcmp(argv[i], "-sname") == 0) { /* -sname NAME */
165 if (i+1 >= argc) {
166 usage_arg(progname, "-sname ");
167 }
168
169 flags.node = ei_chk_strdup(argv[i+1]);
170 i++;
171 flags.use_long_name = 0;
172 } else if (strcmp(argv[i], "-name") == 0) { /* -name NAME */
173 if (i+1 >= argc) {
174 usage_arg(progname, "-name ");
175 }
176
177 flags.node = ei_chk_strdup(argv[i+1]);
178 i++;
179 flags.use_long_name = 1;
180 } else {
181 if (strlen(argv[i]) != 2) {
182 usage_error(progname, argv[i]);
183 }
184
185 switch (argv[i][1]) {
186 case 's':
187 flags.startp = 1;
188 break;
189 case 'q':
190 flags.haltp = 1;
191 break;
192 case 'v':
193 flags.verbosep = 1;
194 break;
195 case 'd':
196 flags.debugp = 1;
197 break;
198 case 'r':
199 flags.randomp = 1;
200 break;
201 case 'e':
202 flags.evalp = 1;
203 break;
204 case 'm':
205 flags.modp = 1;
206 break;
207 case 'c':
208 if (i+1 >= argc) {
209 usage_arg(progname, "-c ");
210 }
211 flags.cookiep = 1;
212 flags.cookie = ei_chk_strdup(argv[i+1]);
213 i++;
214 break;
215 case 'n':
216 if (i+1 >= argc) {
217 usage_arg(progname, "-n ");
218 }
219 flags.node = ei_chk_strdup(argv[i+1]);
220 flags.use_long_name = 1;
221 i++;
222 break;
223 case 'h':
224 if (i+1 >= argc) {
225 usage_arg(progname, "-h ");
226 }
227 flags.hidden = ei_chk_strdup(argv[i+1]);
228 i++;
229 break;
230 case 'x':
231 if (i+1 >= argc) {
232 usage_arg(progname, "-x ");
233 }
234 flags.script = ei_chk_strdup(argv[i+1]);
235 i++;
236 break;
237 case 'a':
238 if (i+1 >= argc) {
239 usage_arg(progname, "-a ");
240 }
241 flags.apply = ei_chk_strdup(argv[i+1]);
242 i++;
243 break;
244 case '?':
245 usage(progname);
246 default:
247 usage_error(progname, argv[i]);
248 }
249 }
250 i++;
251
252 } /* while */
253
254
255 /*
256 * Can't have them both !
257 */
258 if (flags.modp && flags.evalp) {
259 usage(progname);
260 }
261
262 /*
263 * Read an Erlang module from stdin.
264 */
265 if (flags.modp) {
266 modsize = get_module(&module, &modname);
267 }
268
269 if (flags.verbosep || flags.debugp) {
270 fprintf(stderr,"erl_call: "
271 "node = %s\nCookie = %s\n"
272 "flags = %s %s %s\n"
273 "module: name = %s , size = %d\n"
274 "apply = %s\n",
275 (flags.node ? flags.node : ""),
276 (flags.cookie ? flags.cookie : ""),
277 (flags.startp ? "startp" : ""),
278 (flags.verbosep ? "verbosep" : ""),
279 (flags.debugp ? "debugp" : ""),
280 (modname ? modname : ""), modsize,
281 (flags.apply ? flags.apply : "" ));
282 }
283
284 /*
285 * What we, at least, requires !
286 */
287 if (flags.node == NULL) {
288 usage(progname);
289 }
290
291 if (!flags.cookiep) {
292 flags.cookie = NULL;
293 }
294
295 /* FIXME decide how many bits etc or leave to connect_xinit? */
296 creation = (time(NULL) % 3) + 1; /* "random" */
297
298 if (flags.hidden == NULL) {
299 /* As default we are c17@gethostname */
300 i = flags.randomp ? (time(NULL) % 997) : 17;
301 flags.hidden = (char *) ei_chk_malloc(10 + 2 ); /* c17 or cXYZ */
302 #if defined(VXWORKS)
303 sprintf(flags.hidden, "c%d",
304 i < 0 ? (int) taskIdSelf() : i);
305 #else
306 sprintf(flags.hidden, "c%d",
307 i < 0 ? (int) getpid() : i);
308 #endif
309 }
310 {
311 /* A name for our hidden node was specified */
312 char h_hostname[EI_MAXHOSTNAMELEN+1];
313 char h_nodename[MAXNODELEN+1];
314 char *h_alivename=flags.hidden;
315 struct in_addr h_ipadr;
316 char* ct;
317
318 /* gethostname requires len to be max(hostname) + 1 */
319 if (gethostname(h_hostname, EI_MAXHOSTNAMELEN+1) < 0) {
320 fprintf(stderr,"erl_call: failed to get host name: %d\n", errno);
321 exit(1);
322 }
323 if ((hp = ei_gethostbyname(h_hostname)) == 0) {
324 fprintf(stderr,"erl_call: can't resolve hostname %s\n", h_hostname);
325 exit(1);
326 }
327 /* If shortnames, cut off the name at first '.' */
328 if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
329 *ct = '\0';
330 }
331 strncpy(h_hostname, hp->h_name, EI_MAXHOSTNAMELEN);
332 h_hostname[EI_MAXHOSTNAMELEN] = '\0';
333 memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr));
334 if (strlen(h_alivename) + strlen(h_hostname) + 2 > sizeof(h_nodename)) {
335 fprintf(stderr,"erl_call: hostname too long: %s\n", h_hostname);
336 exit(1);
337 }
338 sprintf(h_nodename, "%s@%s", h_alivename, h_hostname);
339
340 if (ei_connect_xinit(&ec, h_hostname, h_alivename, h_nodename,
341 (Erl_IpAddr)&h_ipadr, flags.cookie,
342 (short) creation) < 0) {
343 fprintf(stderr,"erl_call: can't create C node %s; %d\n",
344 h_nodename, erl_errno);
345 exit(1);
346 }
347
348 }
349 if ((p = strchr((const char *)flags.node, (int) '@')) == 0) {
350 strcpy(host_name, ei_thishostname(&ec));
351 host = host_name;
352 } else {
353 *p = 0;
354 host = p+1;
355 }
356
357 /*
358 * Expand name to a real name (may be ip-address)
359 */
360 /* FIXME better error string */
361 if ((hp = ei_gethostbyname(host)) == 0) {
362 fprintf(stderr,"erl_call: can't ei_gethostbyname(%s)\n", host);
363 exit(1);
364 }
365 /* If shortnames, cut off the name at first '.' */
366 if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
367 *ct = '\0';
368 }
369 strncpy(host_name, hp->h_name, EI_MAXHOSTNAMELEN);
370 host_name[EI_MAXHOSTNAMELEN] = '\0';
371 if (strlen(flags.node) + strlen(host_name) + 2 > sizeof(nodename)) {
372 fprintf(stderr,"erl_call: nodename too long: %s\n", flags.node);
373 exit(1);
374 }
375 sprintf(nodename, "%s@%s", flags.node, host_name);
376
377 /*
378 * Try to connect. Start an Erlang system if the
379 * start option is on and no system is running.
380 */
381 if (flags.startp && !flags.haltp) {
382 fd = do_connect(&ec, nodename, &flags);
383 } else if ((fd = ei_connect(&ec, nodename)) < 0) {
384 /* We failed to connect ourself */
385 /* FIXME do we really know we failed because of node not up? */
386 if (flags.haltp) {
387 exit(0);
388 } else {
389 fprintf(stderr,"erl_call: failed to connect to node %s\n",
390 nodename);
391 exit(1);
392 }
393 }
394
395 /* If we are connected and the halt switch is set */
396 if (fd && flags.haltp) {
397 int i = 0;
398 char *p;
399 ei_x_buff reply;
400
401 ei_encode_empty_list(NULL, &i);
402
403 p = (char *)ei_chk_malloc(i);
404 i = 0; /* Reset */
405
406 ei_encode_empty_list(p, &i);
407
408 ei_x_new_with_version(&reply);
409
410 /* FIXME if fails we want to exit != 0 ? */
411 ei_rpc(&ec, fd, "erlang", "halt", p, i, &reply);
412 free(p);
413 ei_x_free(&reply);
414 exit(0);
415 }
416
417 if (flags.verbosep) {
418 fprintf(stderr,"erl_call: we are now connected to node \"%s\"\n",
419 nodename);
420 }
421
422 /*
423 * Compile the module read from stdin.
424 */
425 if (flags.modp && (modname != NULL)) {
426 char fname[256];
427
428 if (strlen(modname) + 4 + 1 > sizeof(fname)) {
429 fprintf(stderr,"erl_call: module name too long: %s\n", modname);
430 exit(1);
431 }
432 strcpy(fname, modname);
433 strcat(fname, ".erl");
434
435 /*
436 * ei_format("[~s,~w]", fname, erl_mk_binary(module, modsize));
437 */
438
439 {
440 int i = 0;
441 char *p;
442 ei_x_buff reply;
443
444 ei_encode_list_header(NULL, &i, 2);
445 ei_encode_string(NULL, &i, fname);
446 ei_encode_binary(NULL, &i, module, modsize);
447 ei_encode_empty_list(NULL, &i);
448
449 p = (char *)ei_chk_malloc(i);
450 i = 0; /* Reset */
451
452 ei_encode_list_header(p, &i, 2);
453 ei_encode_string(p, &i, fname);
454 ei_encode_binary(p, &i, module, modsize);
455 ei_encode_empty_list(p, &i);
456
457 ei_x_new_with_version(&reply);
458
459 if (ei_rpc(&ec, fd, "file", "write_file", p, i, &reply) < 0) {
460 free(p);
461 ei_x_free(&reply);
462 fprintf(stderr,"erl_call: can't write to source file %s\n",
463 fname);
464 exit(1);
465 }
466 free(p);
467 ei_x_free(&reply);
468 }
469
470 /* Compile AND load file on other node */
471
472 {
473 int i = 0;
474 char *p;
475 ei_x_buff reply;
476
477 ei_encode_list_header(NULL, &i, 2);
478 ei_encode_atom(NULL, &i, fname);
479 ei_encode_empty_list(NULL, &i);
480 ei_encode_empty_list(NULL, &i);
481
482 p = (char *)ei_chk_malloc(i);
483 i = 0; /* Reset */
484
485 ei_encode_list_header(p, &i, 2);
486 ei_encode_atom(p, &i, fname);
487 ei_encode_empty_list(p, &i);
488 ei_encode_empty_list(p, &i);
489
490 ei_x_new_with_version(&reply);
491
492 /* erl_format("[~a,[]]", modname) */
493
494 if (ei_rpc(&ec, fd, "c", "c", p, i, &reply) < 0) {
495 free(p);
496 ei_x_free(&reply);
497 fprintf(stderr,"erl_call: can't compile file %s\n", fname);
498 }
499 free(p);
500 /* FIXME complete this code
501 FIXME print out error message as term
502 if (!erl_match(erl_format("{ok,_}"), reply)) {
503 fprintf(stderr,"erl_call: compiler errors\n");
504 }
505 */
506 ei_x_free(&reply);
507 }
508
509 }
510
511 /*
512 * If we loaded any module source code, we can free the buffer
513 * now. This buffer was allocated in read_stdin().
514 */
515 if (module != NULL) {
516 free(module);
517 }
518
519 /*
520 * Eval the Erlang functions read from stdin/
521 */
522 if (flags.evalp) {
523 char *evalbuf;
524 int len;
525
526 len = read_stdin(&evalbuf);
527 {
528 int i = 0;
529 char *p;
530 ei_x_buff reply;
531
532 ei_encode_list_header(NULL, &i, 1);
533 ei_encode_binary(NULL, &i, evalbuf, len);
534 ei_encode_empty_list(NULL, &i);
535
536 p = (char *)ei_chk_malloc(i);
537 i = 0; /* Reset */
538
539 ei_encode_list_header(p, &i, 1);
540 ei_encode_binary(p, &i, evalbuf, len);
541 ei_encode_empty_list(p, &i);
542
543 ei_x_new_with_version(&reply);
544
545 /* erl_format("[~w]", erl_mk_binary(evalbuf,len))) */
546
547 if (ei_rpc(&ec, fd, "erl_eval", "eval_str", p, i, &reply) < 0) {
548 fprintf(stderr,"erl_call: evaluating input failed: %s\n",
549 evalbuf);
550 free(p);
551 free(evalbuf); /* Allocated in read_stdin() */
552 ei_x_free(&reply);
553 exit(1);
554 }
555 i = 0;
556 ei_print_term(stdout,reply.buff,&i);
557 free(p);
558 free(evalbuf); /* Allocated in read_stdin() */
559 ei_x_free(&reply);
560 }
561 }
562 /*
563 * Any Erlang call to be made ?
564 */
565 if (flags.apply != NULL) {
566 char *mod,*fun,*args;
567 ei_x_buff e, reply;
568
569 split_apply_string(flags.apply, &mod, &fun, &args);
570 if (flags.verbosep) {
571 fprintf(stderr,"erl_call: module = %s, function = %s, args = %s\n",
572 mod, fun, args);
573 }
574
575 ei_x_new(&e); /* No version to ei_rpc() */
576
577 if (ei_x_format_wo_ver(&e, args) < 0) {
578 /* FIXME no error message and why -1 ? */
579 exit(-1);
580 }
581
582 ei_x_new_with_version(&reply);
583
584 if (ei_rpc(&ec, fd, mod, fun, e.buff, e.index, &reply) < 0) {
585 /* FIXME no error message and why -1 ? */
586 ei_x_free(&e);
587 ei_x_free(&reply);
588 exit(-1);
589 } else {
590 int i = 0;
591 ei_print_term(stdout,reply.buff,&i);
592 ei_x_free(&e);
593 ei_x_free(&reply);
594 }
595 }
596
597 return(0);
598 }
599
600
601 /***************************************************************************
602 *
603 * XXXXX
604 *
605 ***************************************************************************/
606
607
608 /*
609 * This function does only return on success.
610 */
do_connect(ei_cnode * ec,char * nodename,struct call_flags * flags)611 static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags)
612 {
613 int fd;
614 int start_flags;
615 int r;
616
617 start_flags = ERL_START_ENODE |
618 (flags->use_long_name? ERL_START_LONG : 0) |
619 (flags->verbosep? ERL_START_VERBOSE : 0) |
620 (flags->debugp? ERL_START_DEBUG : 0);
621
622 if ((fd = ei_connect(ec, nodename)) >= 0) {
623 /* success */
624 if (flags->verbosep) {
625 fprintf(stderr,"erl_call: now connected to node %s\n", nodename);
626 }
627 } else {
628 char alive[EI_MAXALIVELEN+1];
629 char *hostname;
630 struct hostent *h;
631 char *cookieargs[3];
632 char **args;
633
634 cookieargs[0] = "-setcookie";
635 cookieargs[1] = flags->cookie;
636 cookieargs[2] = NULL;
637
638 args = (flags->cookie) ? cookieargs : NULL;
639
640 if (!(hostname = strrchr(nodename,'@'))) {
641 return ERL_BADARG;
642 }
643 strncpy(alive,nodename,hostname-nodename);
644 alive[hostname-nodename] = 0x0;
645 hostname++;
646
647 h = ei_gethostbyname(hostname);
648
649
650 if ((r=erl_start_sys(ec,alive,(Erl_IpAddr)(h->h_addr_list[0]),
651 start_flags,flags->script,args)) < 0) {
652 fprintf(stderr,"erl_call: unable to start node, error = %d\n", r);
653 exit(1);
654 }
655
656 if ((fd=ei_connect(ec, nodename)) >= 0) {
657 /* success */
658 if (flags->verbosep) {
659 fprintf(stderr,"erl_call: now connected to node \"%s\"\n",
660 nodename);
661 }
662 } else {
663 /* (failure) */
664 switch (fd) {
665 case ERL_NO_DAEMON:
666 fprintf(stderr,"erl_call: no epmd running\n");
667 exit(1);
668 case ERL_CONNECT_FAIL:
669 fprintf(stderr,"erl_call: connect failed\n");
670 exit(1);
671 case ERL_NO_PORT:
672 fprintf(stderr,"erl_call: node is not running\n");
673 exit(1);
674 case ERL_TIMEOUT:
675 fprintf(stderr,"erl_call: connect timed out\n");
676 exit(1);
677 default:
678 fprintf(stderr,"erl_call: error during connect\n");
679 exit(1);
680 }
681 }
682 }
683
684 return fd;
685 } /* do_connect */
686
687 #define SKIP_SPACE(s) while(isspace((int)*(s))) (s)++
688 #define EAT(s) while (!isspace((int)*(s)) && (*(s) != '\0')) (s)++
689
split_apply_string(char * str,char ** mod,char ** fun,char ** args)690 static void split_apply_string(char *str,
691 char **mod,
692 char **fun,
693 char **args)
694 {
695 char *begin=str;
696 char *start="start";
697 char *empty_list="[]";
698 int len;
699
700 SKIP_SPACE(str);
701 if (*str == '\0') {
702 fprintf(stderr,"erl_call: wrong format of apply string (1)\n");
703 exit(1);
704 }
705
706 EAT(str);
707 len = str-begin;
708 *mod = (char *) ei_chk_calloc(len + 1, sizeof(char));
709 memcpy(*mod, begin, len);
710
711 SKIP_SPACE(str);
712 if (*str == '\0') {
713 *fun = ei_chk_strdup(start);
714 *args = ei_chk_strdup(empty_list);
715 return;
716 }
717 begin = str;
718 EAT(str);
719 len = str-begin;
720 *fun = (char *) ei_chk_calloc(len + 1, sizeof(char));
721 memcpy(*fun, begin, len);
722
723 SKIP_SPACE(str);
724 if (*str == '\0') {
725 *args = ei_chk_strdup(empty_list);
726 return;
727 }
728
729 *args = ei_chk_strdup(str);
730
731 return;
732
733 } /* split_apply_string */
734
735
736 /*
737 * Read from stdin until EOF is reached.
738 * Allocate the buffer needed.
739 */
read_stdin(char ** buf)740 static int read_stdin(char **buf)
741 {
742 int bsize = BUFSIZ;
743 int len = 0;
744 int i;
745 char *tmp = (char *) ei_chk_malloc(bsize);
746
747 while (1) {
748 if ((i = read(0, &tmp[len], bsize-len)) < 0) {
749 fprintf(stderr,"erl_call: can't read stdin, errno = %d", errno);
750 exit(1);
751 } else if (i == 0) {
752 break;
753 } else {
754 len += i;
755 if ((len+50) > bsize) {
756 bsize = len * 2;
757 tmp = (char *) ei_chk_realloc(tmp, bsize);
758 } else {
759 continue;
760 }
761 }
762 } /* while */
763 *buf = tmp;
764 return len;
765
766 } /* read_stdin */
767
768 /*
769 * Get the module from stdin.
770 */
get_module(char ** mbuf,char ** mname)771 static int get_module(char **mbuf, char **mname)
772 {
773 char *tmp;
774 int len,i;
775
776 len = read_stdin(mbuf);
777 /*
778 * Now, get the module name.
779 */
780 if ((tmp = strstr(*mbuf, "-module(")) != NULL) {
781 char *start;
782 tmp += strlen("-module(");
783 while ((*tmp) == ' ') tmp++; /* eat space */
784 start = tmp;
785 while (1) {
786 if (isalnum((int)*tmp) || (*tmp == '_')) {
787 tmp++;
788 continue;
789 } else {
790 break;
791 }
792 } /* while */
793 i = tmp - start;
794 *mname = (char *) ei_chk_calloc(i+1, sizeof(char));
795 memcpy(*mname, start, i);
796 }
797
798 return len;
799
800 } /* get_module */
801
802
803 /***************************************************************************
804 *
805 * Different error reporting functions that output usage
806 *
807 ***************************************************************************/
808
usage_noexit(const char * progname)809 static void usage_noexit(const char *progname) {
810 fprintf(stderr,"\nUsage: %s [-[demqrsv]] [-c Cookie] [-h HiddenName] \n", progname);
811 fprintf(stderr," [-x ErlScript] [-a [Mod [Fun [Args]]]]\n");
812 fprintf(stderr," (-n Node | -sname Node | -name Node)\n\n");
813 #ifdef __WIN32__
814 fprintf(stderr," where: -a apply(Mod,Fun,Args) (e.g -a \"erlang length [[a,b,c]]\"\n");
815 #else
816 fprintf(stderr," where: -a apply(Mod,Fun,Args) (e.g -a 'erlang length [[a,b,c]]'\n");
817 #endif
818 fprintf(stderr," -c cookie string; by default read from ~/.erlang.cookie\n");
819 fprintf(stderr," -d direct Erlang output to ~/.erl_call.out.<Nodename>\n");
820 fprintf(stderr," -e evaluate contents of standard input (e.g echo \"X=1,Y=2,{X,Y}.\"|erl_call -e ...)\n");
821 fprintf(stderr," -h specify a name for the erl_call client node\n");
822 fprintf(stderr," -m read and compile Erlang module from stdin\n");
823 fprintf(stderr," -n name of Erlang node, same as -name\n");
824 fprintf(stderr," -name name of Erlang node, expanded to a fully qualified\n");
825 fprintf(stderr," -sname name of Erlang node, short form will be used\n");
826 fprintf(stderr," -q halt the Erlang node (overrides the -s switch)\n");
827 fprintf(stderr," -r use a random name for the erl_call client node\n");
828 fprintf(stderr," -s start a new Erlang node if necessary\n");
829 fprintf(stderr," -v verbose mode, i.e print some information on stderr\n");
830 fprintf(stderr," -x use specified erl start script, default is erl\n");
831 }
832
usage_arg(const char * progname,const char * switchname)833 static void usage_arg(const char *progname, const char *switchname) {
834 fprintf(stderr, "Missing argument(s) for \'%s\'.\n", switchname);
835 usage_noexit(progname);
836 exit(1);
837 }
838
usage_error(const char * progname,const char * switchname)839 static void usage_error(const char *progname, const char *switchname) {
840 fprintf(stderr, "Illegal argument \'%s\'.\n", switchname);
841 usage_noexit(progname);
842 exit(1);
843 }
844
usage(const char * progname)845 static void usage(const char *progname) {
846 usage_noexit(progname);
847 exit(0);
848 }
849
850 /***************************************************************************
851 *
852 * Utility functions
853 *
854 ***************************************************************************/
855
ei_chk_malloc(size_t size)856 static void* ei_chk_malloc(size_t size)
857 {
858 void *p = malloc(size);
859 if (p == NULL) {
860 fprintf(stderr,"erl_call: insufficient memory\n");
861 exit(1);
862 }
863 return p;
864 }
865
ei_chk_calloc(size_t nmemb,size_t size)866 static void* ei_chk_calloc(size_t nmemb, size_t size)
867 {
868 void *p = calloc(nmemb, size);
869 if (p == NULL) {
870 fprintf(stderr,"erl_call: insufficient memory\n");
871 exit(1);
872 }
873 return p;
874 }
875
ei_chk_realloc(void * old,size_t size)876 static void* ei_chk_realloc(void *old, size_t size)
877 {
878 void *p = realloc(old, size);
879 if (!p) {
880 fprintf(stderr, "erl_call: cannot reallocate %u bytes of memory from %p\n",
881 (unsigned) size, old);
882 exit (1);
883 }
884 return p;
885 }
886
ei_chk_strdup(char * s)887 static char* ei_chk_strdup(char *s)
888 {
889 char *p = strdup(s);
890 if (p == NULL) {
891 fprintf(stderr,"erl_call: insufficient memory\n");
892 exit(1);
893 }
894 return p;
895 }
896