~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to erts/emulator/beam/erl_bif_port.c

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-08-05 20:54:29 UTC
  • mfrom: (6.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20090805205429-pm4pnwew8axraosl
Tags: 1:13.b.1-dfsg-5
* Fixed parentheses in Emacs mode (closes: #536891).
* Removed unnecessary conflicts with erlang-manpages package.
* Added workaround for #475459: disabled threads on sparc architecture.
  This breaks wxErlang, so it's only a temporary solution.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
#include <ctype.h>
29
29
 
 
30
#define ERTS_WANT_EXTERNAL_TAGS
30
31
#include "sys.h"
31
32
#include "erl_vm.h"
32
33
#include "erl_sys_driver.h"
46
47
 
47
48
static int open_port(Process* p, Eterm name, Eterm settings, int *err_nump);
48
49
static byte* convert_environment(Process* p, Eterm env);
 
50
static char **convert_args(Eterm);
 
51
static void free_args(char **);
 
52
 
 
53
char *erts_default_arg0 = "default";
49
54
 
50
55
BIF_RETTYPE open_port_2(BIF_ALIST_2)
51
56
{
278
283
    if (erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(p)) {
279
284
        profile_runnable_port(p, am_active);
280
285
    }
281
 
    size = encode_size_struct(BIF_ARG_3, TERM_TO_BINARY_DFLAGS);
 
286
    size = erts_encode_ext_size(BIF_ARG_3);
282
287
    if (size > sizeof(port_input))
283
288
        bytes = erts_alloc(ERTS_ALC_T_PORT_CALL_BUF, size);
284
289
 
285
290
    endp = bytes;
286
 
    if (erts_to_external_format(NULL, BIF_ARG_3, &endp, NULL, NULL) || !endp) {
287
 
        erl_exit(1, "%s, line %d: bad term: %x\n",
288
 
                 __FILE__, __LINE__, BIF_ARG_3);
289
 
    }
 
291
    erts_encode_ext(BIF_ARG_3, &endp);
290
292
 
291
293
    real_size = endp - bytes;
292
294
    if (real_size > size) {
336
338
        /* Error or a binary without magic/ with wrong magic */
337
339
        goto error;
338
340
    }
339
 
    result_size = erts_decoded_size(port_resp, ret, 0);
 
341
    result_size = erts_decode_ext_size(port_resp, ret, 0);
340
342
    if (result_size < 0) {
341
343
        goto error;
342
344
    }
343
345
    hp = HAlloc(BIF_P, result_size);
344
346
    hp_end = hp + result_size;
345
347
    endp = port_resp;
346
 
    if ((res = erts_from_external_format(NULL, &hp, &endp, &MSO(BIF_P)))
347
 
        == THE_NON_VALUE) {
 
348
    res = erts_decode_ext(&hp, &MSO(BIF_P), &endp);
 
349
    if (res == THE_NON_VALUE) {
348
350
        goto error;
349
351
    }
350
352
    HRelease(BIF_P, hp_end, hp);
552
554
 * -3 if argument parsing failed or we are out of ports (*err_nump should contain
553
555
 * either BADARG or SYSTEM_LIMIT).
554
556
 */
 
557
 
555
558
static int
556
559
open_port(Process* p, Eterm name, Eterm settings, int *err_nump)
557
560
{
578
581
    opts.wd = NULL;
579
582
    opts.envir = NULL;
580
583
    opts.exit_status = 0;
 
584
    opts.spawn_type = ERTS_SPAWN_ANY; 
 
585
    opts.argv = NULL;
581
586
    binary_io = 0;
582
587
    soft_eof = 0;
583
588
    linebuf = 0;
625
630
                        goto badarg;
626
631
                    }
627
632
                    opts.envir = (char *) bytes;
 
633
                } else if (option == am_args) {
 
634
                    char **av;
 
635
                    char **oav = opts.argv;
 
636
                    if ((av = convert_args(*tp)) == NULL) {
 
637
                        goto badarg;
 
638
                    }
 
639
                    opts.argv = av;
 
640
                    if (oav) {
 
641
                        opts.argv[0] = oav[0];
 
642
                        oav[0] = erts_default_arg0;
 
643
                        free_args(oav);
 
644
                    }
 
645
 
 
646
                } else if (option == am_arg0) {
 
647
                    char *a0;
 
648
                    int n;
 
649
                    if (is_nil(*tp)) {
 
650
                        n = 0;
 
651
                    } else if( (n = is_string(*tp)) == 0) {
 
652
                        goto badarg;
 
653
                    }
 
654
                    a0 = (char *) erts_alloc(ERTS_ALC_T_TMP, 
 
655
                                            (n + 1) * sizeof(byte));
 
656
                    if (intlist_to_buf(*tp, a0, n) != n) {
 
657
                        erl_exit(1, "%s:%d: Internal error\n",
 
658
                                 __FILE__, __LINE__);
 
659
                    }
 
660
                    a0[n] = '\0';                   
 
661
                    if (opts.argv == NULL) {
 
662
                        opts.argv = erts_alloc(ERTS_ALC_T_TMP, 
 
663
                                               2 * sizeof(char **));
 
664
                        opts.argv[0] = a0;
 
665
                        opts.argv[1] = NULL;
 
666
                    } else {
 
667
                        if (opts.argv[0] != erts_default_arg0) {
 
668
                            erts_free(ERTS_ALC_T_TMP, opts.argv[0]);
 
669
                        }
 
670
                        opts.argv[0] = a0;
 
671
                    }
628
672
                } else if (option == am_cd) {
629
673
                    Eterm iolist;
630
674
                    Eterm heap[4];
715
759
        if (arity == make_arityval(0)) {
716
760
            goto badarg;
717
761
        }
718
 
 
719
 
        if (*tp == am_spawn) {  /* A process port */
720
 
            if (arity != make_arityval(2)) {
721
 
                goto badarg;
722
 
            }
723
 
            name = tp[1];
724
 
            if (is_atom(name)) {
725
 
                name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
726
 
                                               atom_tab(atom_val(name))->len+1);
727
 
                sys_memcpy((void *) name_buf,
728
 
                           (void *) atom_tab(atom_val(name))->name, 
729
 
                           atom_tab(atom_val(name))->len);
730
 
                name_buf[atom_tab(atom_val(name))->len] = '\0';
731
 
            } else if ((i = is_string(name))) {
732
 
                name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
733
 
                if (intlist_to_buf(name, name_buf, i) != i)
734
 
                    erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
735
 
                name_buf[i] = '\0';
736
 
            } else {
737
 
                goto badarg;
738
 
            }
 
762
    
 
763
        if (*tp == am_spawn || *tp == am_spawn_driver) {        /* A process port */
 
764
            if (arity != make_arityval(2)) {
 
765
                goto badarg;
 
766
            }
 
767
            name = tp[1];
 
768
            if (is_atom(name)) {
 
769
                name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
 
770
                                               atom_tab(atom_val(name))->len+1);
 
771
                sys_memcpy((void *) name_buf,
 
772
                           (void *) atom_tab(atom_val(name))->name, 
 
773
                           atom_tab(atom_val(name))->len);
 
774
                name_buf[atom_tab(atom_val(name))->len] = '\0';
 
775
            } else if ((i = is_string(name))) {
 
776
                name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
 
777
                if (intlist_to_buf(name, name_buf, i) != i)
 
778
                    erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
 
779
                name_buf[i] = '\0';
 
780
            } else {
 
781
                goto badarg;
 
782
            }
 
783
            if (*tp == am_spawn_driver) {
 
784
                opts.spawn_type = ERTS_SPAWN_DRIVER;
 
785
            }
 
786
            driver = &spawn_driver;
 
787
        } else if (*tp == am_spawn_executable) {        /* A program */
 
788
            /*
 
789
             * {spawn_executable,Progname}
 
790
             */
 
791
            
 
792
            if (arity != make_arityval(2)) {
 
793
                goto badarg;
 
794
            }
 
795
            name = tp[1];
 
796
            if (is_atom(name)) {
 
797
                name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
 
798
                                               atom_tab(atom_val(name))->len+1);
 
799
                sys_memcpy((void *) name_buf,
 
800
                           (void *) atom_tab(atom_val(name))->name, 
 
801
                           atom_tab(atom_val(name))->len);
 
802
                name_buf[atom_tab(atom_val(name))->len] = '\0';
 
803
            } else if ((i = is_string(name))) {
 
804
                name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
 
805
                if (intlist_to_buf(name, name_buf, i) != i)
 
806
                    erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
 
807
                name_buf[i] = '\0';
 
808
            } else {
 
809
                goto badarg;
 
810
            }
 
811
            opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
739
812
            driver = &spawn_driver;
740
813
        } else if (*tp == am_fd) { /* An fd port */
741
814
            int n;
767
840
        }
768
841
    }
769
842
 
 
843
    if ((driver != &spawn_driver && opts.argv != NULL) ||
 
844
        (driver == &spawn_driver && 
 
845
         opts.spawn_type != ERTS_SPAWN_EXECUTABLE && 
 
846
         opts.argv != NULL)) {
 
847
        /* Argument vector only if explicit spawn_executable */
 
848
        goto badarg;
 
849
    }
 
850
        
 
851
 
770
852
    if (driver != &spawn_driver && opts.exit_status) {
771
853
        goto badarg;
772
854
    }
773
 
 
 
855
    
774
856
    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
775
857
        trace_virtual_sched(p, am_out);
776
858
    }
777
 
 
 
859
    
778
860
 
779
861
    erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
780
862
 
807
889
        erts_port_status_bor_set(&erts_port[port_num],
808
890
                                 ERTS_PORT_SFLG_LINEBUF_IO);
809
891
    }
810
 
 
 
892
 
811
893
 do_return:
812
894
    if (name_buf)
813
895
        erts_free(ERTS_ALC_T_TMP, (void *) name_buf);
 
896
    if (opts.argv) {
 
897
        free_args(opts.argv);
 
898
    }
814
899
    return port_num;
815
 
 
 
900
    
816
901
 badarg:
817
902
    *err_nump = BADARG;
818
903
    OPEN_PORT_ERROR(-3);
820
905
#undef OPEN_PORT_ERROR
821
906
}
822
907
 
 
908
static char **convert_args(Eterm l)
 
909
{
 
910
    char **pp;
 
911
    char *b;
 
912
    int n;
 
913
    int i = 0;
 
914
    Eterm str;
 
915
    /* We require at least one element in list (argv[0]) */
 
916
    if (is_not_list(l) && is_not_nil(l)) {
 
917
        return NULL;
 
918
    }
 
919
    n = list_length(l);
 
920
    pp = erts_alloc(ERTS_ALC_T_TMP, (n + 2) * sizeof(char **));
 
921
    pp[i++] = erts_default_arg0;
 
922
    while (is_list(l)) {
 
923
        str = CAR(list_val(l));
 
924
 
 
925
        if (is_nil(str)) {
 
926
            n = 0;
 
927
        } else if( (n = is_string(str)) == 0) {
 
928
            /* Not a string... */
 
929
            int j;
 
930
            for (j = 1; j < i; ++j)
 
931
                erts_free(ERTS_ALC_T_TMP, pp[j]);
 
932
            erts_free(ERTS_ALC_T_TMP, pp);
 
933
            return NULL;
 
934
        }
 
935
        b = (char *) erts_alloc(ERTS_ALC_T_TMP, (n + 1) * sizeof(byte));
 
936
        pp[i++] = (char *) b;
 
937
        if (intlist_to_buf(str, b, n) != n)
 
938
            erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
 
939
        b[n] = '\0';
 
940
        l = CDR(list_val(l));
 
941
    }
 
942
    pp[i] = NULL;
 
943
    return pp;
 
944
}
 
945
 
 
946
static void free_args(char **av)
 
947
{
 
948
    int i;
 
949
    if (av == NULL)
 
950
        return;
 
951
    for (i = 0; av[i] != NULL; ++i) {
 
952
        if (av[i] != erts_default_arg0) {
 
953
            erts_free(ERTS_ALC_T_TMP, av[i]);
 
954
        }
 
955
    }
 
956
    erts_free(ERTS_ALC_T_TMP, av);
 
957
}
 
958
    
 
959
 
823
960
static byte* convert_environment(Process* p, Eterm env)
824
961
{
825
962
    Eterm all;