Esempio n. 1
0
int main(int argc, char* argv[])
{
	char** copyv;
	int i;

	/* duplicate the arguments */
	copyv = alloca((argc+1) * sizeof(char*));
	for(i=0;i<argc;++i) {
		copyv[i] = alloca(strlen(argv[i]) + 1);
		strcpy(copyv[i], argv[i]);
	}
	copyv[i] = 0;

	/* set the entry point to restart the program */
	if (sigsetjmp(OS_HUP, 1) != 0) {

		/* restart the program */
		execv(copyv[0], copyv);

		/* abort if fail */
		abort();
	}

	if (target_init() != 0)
		return EXIT_FAILURE;

	if (file_init() != 0) {
		target_done();
		return EXIT_FAILURE;
	}

	if (os_main(argc, argv) != 0) {
		file_done();
		target_done();
		return EXIT_FAILURE;
	}

	file_done();
	target_done();

	return EXIT_SUCCESS;
}
Esempio n. 2
0
File: file.c Progetto: 0w/moai-dev
/*
 * file_connect() gets called from Curl_protocol_connect() to allow us to
 * do protocol-specific actions at connect-time.  We emulate a
 * connect-then-transfer protocol and "connect" to the file here
 */
static CURLcode file_connect(struct connectdata *conn, bool *done)
{
  struct SessionHandle *data = conn->data;
  char *real_path = curl_easy_unescape(data, data->state.path, 0, NULL);
  struct FILEPROTO *file;
  int fd;
#ifdef DOS_FILESYSTEM
  int i;
  char *actual_path;
#endif

  if(!real_path)
    return CURLE_OUT_OF_MEMORY;

  /* If there already is a protocol-specific struct allocated for this
     sessionhandle, deal with it */
  Curl_reset_reqproto(conn);

  if(!data->state.proto.file) {
    file = calloc(sizeof(struct FILEPROTO), 1);
    if(!file) {
      free(real_path);
      return CURLE_OUT_OF_MEMORY;
    }
    data->state.proto.file = file;
  }
  else {
    /* file is not a protocol that can deal with "persistancy" */
    file = data->state.proto.file;
    Curl_safefree(file->freepath);
    if(file->fd != -1)
      close(file->fd);
    file->path = NULL;
    file->freepath = NULL;
    file->fd = -1;
  }

#ifdef DOS_FILESYSTEM
  /* If the first character is a slash, and there's
     something that looks like a drive at the beginning of
     the path, skip the slash.  If we remove the initial
     slash in all cases, paths without drive letters end up
     relative to the current directory which isn't how
     browsers work.

     Some browsers accept | instead of : as the drive letter
     separator, so we do too.

     On other platforms, we need the slash to indicate an
     absolute pathname.  On Windows, absolute paths start
     with a drive letter.
  */
  actual_path = real_path;
  if((actual_path[0] == '/') &&
      actual_path[1] &&
      (actual_path[2] == ':' || actual_path[2] == '|'))
  {
    actual_path[2] = ':';
    actual_path++;
  }

  /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
  for (i=0; actual_path[i] != '\0'; ++i)
    if(actual_path[i] == '/')
      actual_path[i] = '\\';

  fd = open_readonly(actual_path, O_RDONLY|O_BINARY); /* no CR/LF translation */
  file->path = actual_path;
#else
  fd = open_readonly(real_path, O_RDONLY);
  file->path = real_path;
#endif
  file->freepath = real_path; /* free this when done */

  file->fd = fd;
  if(!data->set.upload && (fd == -1)) {
    failf(data, "Couldn't open file %s", data->state.path);
    file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
    return CURLE_FILE_COULDNT_READ_FILE;
  }
  *done = TRUE;

  return CURLE_OK;
}
Esempio n. 3
0
File: file.c Progetto: jgsogo/curl
/*
 * file_connect() gets called from Curl_protocol_connect() to allow us to
 * do protocol-specific actions at connect-time.  We emulate a
 * connect-then-transfer protocol and "connect" to the file here
 */
static CURLcode file_connect(struct connectdata *conn, bool *done)
{
  struct SessionHandle *data = conn->data;
  char *real_path;
  struct FILEPROTO *file = data->req.protop;
  int fd;
#ifdef DOS_FILESYSTEM
  int i;
  char *actual_path;
#endif
  int real_path_len;

  real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len);
  if(!real_path)
    return CURLE_OUT_OF_MEMORY;

#ifdef DOS_FILESYSTEM
  /* If the first character is a slash, and there's
     something that looks like a drive at the beginning of
     the path, skip the slash.  If we remove the initial
     slash in all cases, paths without drive letters end up
     relative to the current directory which isn't how
     browsers work.

     Some browsers accept | instead of : as the drive letter
     separator, so we do too.

     On other platforms, we need the slash to indicate an
     absolute pathname.  On Windows, absolute paths start
     with a drive letter.
  */
  actual_path = real_path;
  if((actual_path[0] == '/') &&
      actual_path[1] &&
     (actual_path[2] == ':' || actual_path[2] == '|')) {
    actual_path[2] = ':';
    actual_path++;
    real_path_len--;
  }

  /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
  for(i=0; i < real_path_len; ++i)
    if(actual_path[i] == '/')
      actual_path[i] = '\\';
    else if(!actual_path[i]) /* binary zero */
      return CURLE_URL_MALFORMAT;

  fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
  file->path = actual_path;
#else
  if(memchr(real_path, 0, real_path_len))
    /* binary zeroes indicate foul play */
    return CURLE_URL_MALFORMAT;

  fd = open_readonly(real_path, O_RDONLY);
  file->path = real_path;
#endif
  file->freepath = real_path; /* free this when done */

  file->fd = fd;
  if(!data->set.upload && (fd == -1)) {
    failf(data, "Couldn't open file %s", data->state.path);
    file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
    return CURLE_FILE_COULDNT_READ_FILE;
  }
  *done = TRUE;

  return CURLE_OK;
}
Esempio n. 4
0
int main( int argc, char * * argv, char * * arg_environ )
{
    int                     n;
    char                  * s;
    struct bjam_option      optv[N_OPTS];
    char            const * all = "all";
    int                     status;
    int                     arg_c = argc;
    char          *       * arg_v = argv;
    char            const * progname = argv[0];
    module_t              * environ_module;

#if defined(unix) || defined(__unix)
    sigset_t sigmask;
    struct sigaction sa;

    sigemptyset(&sigmask);
    sigaddset(&sigmask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &sigmask, NULL);
    sa.sa_flags = 0;
    sa.sa_handler = child_sig_handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGCHLD, &sa, NULL);
    sigemptyset(&empty_sigmask);
#endif

    saved_argv0 = argv[0];

    BJAM_MEM_INIT();

# ifdef OS_MAC
    InitGraf(&qd.thePort);
# endif

    --argc;
    ++argv;

    if ( getoptions( argc, argv, "-:l:m:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
    {
        printf( "\nusage: %s [ options ] targets...\n\n", progname );

        printf( "-a      Build all targets, even if they are current.\n" );
        printf( "-dx     Set the debug level to x (0-9).\n" );
        printf( "-fx     Read x instead of Jambase.\n" );
        /* printf( "-g      Build from newest sources first.\n" ); */
        printf( "-jx     Run up to x shell commands concurrently.\n" );
        printf( "-lx     Limit actions to x number of seconds after which they are stopped.\n" );
        printf( "-mx     Limit action output buffer to x kb's of data, after which action output is read and ignored.\n" );
        printf( "-n      Don't actually execute the updating actions.\n" );
        printf( "-ox     Write the updating actions to file x.\n" );
        printf( "-px     x=0, pipes action stdout and stderr merged into action output.\n" );
        printf( "-q      Quit quickly as soon as a target fails.\n" );
        printf( "-sx=y   Set variable x=y, overriding environment.\n" );
        printf( "-tx     Rebuild x, even if it is up-to-date.\n" );
        printf( "-v      Print the version of jam and exit.\n" );
        printf( "--x     Option is ignored.\n\n" );

        exit( EXITBAD );
    }

    /* Version info. */
    if ( ( s = getoptval( optv, 'v', 0 ) ) )
    {
        printf( "Boost.Jam  " );
        printf( "Version %s. %s.\n", VERSION, OSMINOR );
        printf( "   Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.  \n" );
        printf( "   Copyright 2001 David Turner.\n" );
        printf( "   Copyright 2001-2004 David Abrahams.\n" );
        printf( "   Copyright 2002-2008 Rene Rivera.\n" );
        printf( "   Copyright 2003-2008 Vladimir Prus.\n" );

        return EXITOK;
    }

    /* Pick up interesting options. */
    if ( ( s = getoptval( optv, 'n', 0 ) ) )
        globs.noexec++, globs.debug[2] = 1;

    if ( ( s = getoptval( optv, 'p', 0 ) ) )
    {
        /* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action
         * stdout and stderr.
         */
        globs.pipe_action = atoi( s );
        if ( ( 3 < globs.pipe_action ) || ( globs.pipe_action < 0 ) )
        {
            printf(
                "Invalid pipe descriptor '%d', valid values are -p[0..3].\n",
                globs.pipe_action );
            exit( EXITBAD );
        }
    }

    if ( ( s = getoptval( optv, 'q', 0 ) ) )
        globs.quitquick = 1;

    if ( ( s = getoptval( optv, 'a', 0 ) ) )
        anyhow++;

    if ( ( s = getoptval( optv, 'j', 0 ) ) )
    {
        globs.jobs = atoi( s );
        if (globs.jobs == 0)
        {
            printf("Invalid value for the '-j' option.\n");
            exit(EXITBAD);
        }
    }

    if ( ( s = getoptval( optv, 'g', 0 ) ) )
        globs.newestfirst = 1;

    if ( ( s = getoptval( optv, 'l', 0 ) ) )
        globs.timeout = atoi( s );

    if ( ( s = getoptval( optv, 'm', 0 ) ) )
        globs.maxbuf = atoi( s ) * 1024;

    /* Turn on/off debugging */
    for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n )
    {
        int i;

        /* First -d, turn off defaults. */
        if ( !n )
            for ( i = 0; i < DEBUG_MAX; ++i )
                globs.debug[i] = 0;

        i = atoi( s );

        if ( ( i < 0 ) || ( i >= DEBUG_MAX ) )
        {
            printf( "Invalid debug level '%s'.\n", s );
            continue;
        }

        /* n turns on levels 1-n. */
        /* +n turns on level n. */
        if ( *s == '+' )
            globs.debug[i] = 1;
        else while ( i )
            globs.debug[i--] = 1;
    }

    constants_init();

    {
        PROFILE_ENTER( MAIN );

#ifdef HAVE_PYTHON
        {
            PROFILE_ENTER( MAIN_PYTHON );
            Py_Initialize();
            {
                static PyMethodDef BjamMethods[] = {
                    {"call", bjam_call, METH_VARARGS,
                     "Call the specified bjam rule."},
                    {"import_rule", bjam_import_rule, METH_VARARGS,
                     "Imports Python callable to bjam."},
                    {"define_action", bjam_define_action, METH_VARARGS,
                     "Defines a command line action."},
                    {"variable", bjam_variable, METH_VARARGS,
                     "Obtains a variable from bjam's global module."},
                    {"backtrace", bjam_backtrace, METH_VARARGS,
                     "Returns bjam backtrace from the last call into Python."},
                    {"caller", bjam_caller, METH_VARARGS,
                     "Returns the module from which the last call into Python is made."},
                    {NULL, NULL, 0, NULL}
                };

                Py_InitModule( "bjam", BjamMethods );
            }
            PROFILE_EXIT( MAIN_PYTHON );
        }
#endif

#ifndef NDEBUG
        run_unit_tests();
#endif
#if YYDEBUG != 0
        if ( DEBUG_PARSE )
            yydebug = 1;
#endif

        /* Set JAMDATE. */
        var_set( root_module(), constant_JAMDATE, list_new( L0, outf_time(time(0)) ), VAR_SET );

        /* Set JAM_VERSION. */
        var_set( root_module(), constant_JAM_VERSION,
                 list_new( list_new( list_new( L0,
                   object_new( VERSION_MAJOR_SYM ) ),
                   object_new( VERSION_MINOR_SYM ) ),
                   object_new( VERSION_PATCH_SYM ) ),
                   VAR_SET );

        /* Set JAMUNAME. */
#if defined(unix) || defined(__unix)
        {
            struct utsname u;

            if ( uname( &u ) >= 0 )
            {
                var_set( root_module(), constant_JAMUNAME,
                         list_new(
                             list_new(
                                 list_new(
                                     list_new(
                                         list_new( L0,
                                            object_new( u.sysname ) ),
                                         object_new( u.nodename ) ),
                                     object_new( u.release ) ),
                                 object_new( u.version ) ),
                             object_new( u.machine ) ), VAR_SET );
            }
        }
#endif /* unix */

        /* Load up environment variables. */

        /* First into the global module, with splitting, for backward
         * compatibility.
         */
        var_defines( root_module(), use_environ, 1 );

        environ_module = bindmodule( constant_ENVIRON );
        /* Then into .ENVIRON, without splitting. */
        var_defines( environ_module, use_environ, 0 );

        /*
         * Jam defined variables OS & OSPLAT. We load them after environment, so
         * that setting OS in environment does not change Jam's notion of the
         * current platform.
         */
        var_defines( root_module(), othersyms, 1 );

        /* Load up variables set on command line. */
        for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n )
        {
            char *symv[2];
            symv[ 0 ] = s;
            symv[ 1 ] = 0;
            var_defines( root_module(), symv, 1 );
            var_defines( environ_module, symv, 0 );
        }

        /* Set the ARGV to reflect the complete list of arguments of invocation.
         */
        for ( n = 0; n < arg_c; ++n )
        {
            var_set( root_module(), constant_ARGV, list_new( L0, object_new( arg_v[n] ) ), VAR_APPEND );
        }

        /* Initialize built-in rules. */
        load_builtins();

        /* Add the targets in the command line to the update list. */
        for ( n = 1; n < arg_c; ++n )
        {
            if ( arg_v[ n ][ 0 ] == '-' )
            {
                char * f = "-:l:d:j:f:gs:t:ano:qv";
                for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break;
                if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n;
            }
            else
            {
                OBJECT * target = object_new( arg_v[ n ] );
                mark_target_for_updating( target );
                object_free( target );
            }
        }

        if (!targets_to_update())
        {
            mark_target_for_updating( constant_all );
        }

        /* Parse ruleset. */
        {
            FRAME frame[ 1 ];
            frame_init( frame );
            for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n )
            {
                OBJECT * filename = object_new( s );
                parse_file( filename, frame );
                object_free( filename );
            }

            if ( !n )
            {
                parse_file( constant_plus, frame );
            }
        }

        status = yyanyerrors();

        /* Manually touch -t targets. */
        for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n )
        {
            OBJECT * target = object_new( s );
            touch_target( target );
            object_free( target );
        }

        /* If an output file is specified, set globs.cmdout to that. */
        if ( ( s = getoptval( optv, 'o', 0 ) ) )
        {
            if ( !( globs.cmdout = fopen( s, "w" ) ) )
            {
                printf( "Failed to write to '%s'\n", s );
                exit( EXITBAD );
            }
            ++globs.noexec;
        }

        /* The build system may set the PARALLELISM variable to override -j
           options.  */
        {
            LIST *p = L0;
            p = var_get ( root_module(), constant_PARALLELISM );
            if ( p )
            {
                int j = atoi( object_str( p->value ) );
                if ( j == -1 )
                {
                    printf( "Invalid value of PARALLELISM: %s\n", object_str( p->value ) );
                }
                else
                {
                    globs.jobs = j;
                }
            }
        }

        /* KEEP_GOING overrides -q option. */
        {
            LIST *p = L0;
            p = var_get( root_module(), constant_KEEP_GOING );
            if ( p )
            {
                int v = atoi( object_str( p->value ) );
                if ( v == 0 )
                    globs.quitquick = 1;
                else
                    globs.quitquick = 0;
            }
        }

        /* Now make target. */
        {
            PROFILE_ENTER( MAIN_MAKE );

            LIST * targets = targets_to_update();
            if (targets)
            {
                int targets_count = list_length( targets );
                OBJECT * * targets2 = (OBJECT * *)
                    BJAM_MALLOC( targets_count * sizeof( OBJECT * ) );
                int n = 0;
                for ( ; targets; targets = list_next( targets ) )
                    targets2[ n++ ] = targets->value;
                status |= make( targets_count, targets2, anyhow );
                BJAM_FREE( (void *)targets2 );
            }
            else
            {
                status = last_update_now_status;
            }

            PROFILE_EXIT( MAIN_MAKE );
        }

        PROFILE_EXIT( MAIN );
    }

    if ( DEBUG_PROFILE )
        profile_dump();

    
#ifdef OPT_HEADER_CACHE_EXT
    hcache_done();
#endif

    clear_targets_to_update();

    /* Widely scattered cleanup. */
    file_done();
    rules_done();
    stamps_done();
    search_done();
    class_done();
    modules_done();
    regex_done();
    exec_done();
    pwd_done();
    path_done();
    function_done();
    list_done();
    constants_done();
    object_done();

    /* Close cmdout. */
    if ( globs.cmdout )
        fclose( globs.cmdout );

#ifdef HAVE_PYTHON
    Py_Finalize();
#endif

    BJAM_MEM_CLOSE();

    return status ? EXITBAD : EXITOK;
}
Esempio n. 5
0
/**
 * Gets the current timeout value to use for the main loop
 *
 * First check to see if any active groups have an expired timeout, and
 * handle that timeout.  Once all expired timeouts have been handled, find
 * the active group with the earliest timeout and return the time until that
 * timeout.  If there are no active groups, return NULL.
 */
struct timeval *getrecenttimeout(void)
{
    static struct timeval tv = {0,0};
    struct timeval current_timestamp, min_timestamp;
    int i, found_timeout, done, sent_naks;
    struct group_list_t *group;
    unsigned int section, nak_count;
    unsigned char *naks;

    gettimeofday(&current_timestamp, NULL);
    done = 0;
    while (!done) {
        found_timeout = 0;
        done = 1;
        for (i = 0; i < MAXLIST; i++) {
            group = &group_list[i];
            if (group->group_id != 0) {
                if (cmptimestamp(current_timestamp, group->timeout_time) >= 0) {
                    switch (group->phase) {
                    case PHASE_REGISTERED:
                        send_register(group);
                        break;
                    case PHASE_RECEIVING:
                    case PHASE_MIDGROUP:
                        glog1(group, "Transfer timed out");
                        send_abort(group, "Transfer timed out");
                        break;
                    case PHASE_COMPLETE:
                        send_complete(group, 0);
                        break;
                    }
                    done = 0;
                } else if ((!found_timeout) ||
                           (cmptimestamp(group->timeout_time,
                                         min_timestamp) < 0)) {
                    glog5(group, "found min timeout time: %d:%06d",
                                 group->timeout_time.tv_sec,
                                 group->timeout_time.tv_usec);
                    min_timestamp = group->timeout_time;
                    found_timeout = 1;
                }
                // Check for a NAK timeout for sending a STATUS or COMPLETE
                if ((group->fileinfo.nak_time.tv_sec != 0) &&
                        cmptimestamp(current_timestamp,
                                     group->fileinfo.nak_time) >= 0) {
                    group->fileinfo.nak_time.tv_sec = 0;
                    group->fileinfo.nak_time.tv_usec = 0;
                    // Send NAKs
                    sent_naks = 0;
                retry_naks:
                    for (section = group->fileinfo.nak_section_first;
                            section < group->fileinfo.nak_section_last;
                            section++) {
                        naks = NULL;
                        nak_count = get_naks(group, section, &naks);
                        glog3(group, "read %d NAKs for section %d",
                                     nak_count, section);
                        if (nak_count > 0) {
                            send_status(group, section, naks, nak_count);
                            sent_naks = 1;
                        }
                        free(naks);
                        naks = NULL;
                    }
                    if (file_done(group, 1)) {
                        glog2(group, "File transfer complete");
                        send_complete(group, 0);
                        file_cleanup(group, 0);
                    } else if (group->fileinfo.got_done && !sent_naks) {
                        // We didn't send any NAKs since the last time
                        // but the server is asking for some,
                        // so check all prior sections
                        group->fileinfo.nak_section_last = 
                                group->fileinfo.nak_section_first;
                        group->fileinfo.nak_section_first = 0;
                        group->fileinfo.got_done = 0;
                        goto retry_naks;
                    }
                } else if ((group->fileinfo.nak_time.tv_sec != 0) &&
                           ((!found_timeout) ||
                            (cmptimestamp(group->fileinfo.nak_time,
                                          min_timestamp) < 0))) {
                    glog5(group, "found min nak time: %d:%06d",
                         group->fileinfo.nak_time.tv_sec,
                         group->fileinfo.nak_time.tv_usec);
                    min_timestamp = group->fileinfo.nak_time;
                    found_timeout = 1;
                }
                // Check congestion control feedback timer
                if (!group->isclr) {
                    if ((group->cc_time.tv_sec != 0) &&
                            (cmptimestamp(current_timestamp,
                                          group->cc_time) >= 0)) {
                        send_cc_ack(group);
                    } else if ((group->cc_time.tv_sec != 0) &&
                               ((!found_timeout) ||
                                (cmptimestamp(group->cc_time,
                                              min_timestamp) < 0))) {
                        glog5(group, "found min CC time: %d:%06d",
                             group->cc_time.tv_sec, group->cc_time.tv_usec);
                        min_timestamp = group->cc_time;
                        found_timeout = 1;
                    }
                }
            }
        }
        // Check timeout for proxy key request
        if (has_proxy && (proxy_pubkey.key == 0)) {
            if (cmptimestamp(current_timestamp, next_keyreq_time) >= 0) {
                send_key_req();
                done = 0;
            } else if ((!found_timeout) ||
                       (cmptimestamp(next_keyreq_time, min_timestamp) < 0)) {
                min_timestamp = next_keyreq_time;
                found_timeout = 1;
            }
        }
        // Check timeout for sending heartbeat
        if (hbhost_count) {
            if (cmptimestamp(current_timestamp, next_hb_time) >= 0) {
                send_hb_request(listener, hb_hosts, hbhost_count,
                                &next_hb_time, hb_interval, uid);
                done = 0;
            } else if ((!found_timeout) ||
                       (cmptimestamp(next_hb_time, min_timestamp) < 0)) {
                min_timestamp = next_hb_time;
                found_timeout = 1;
            }
        }

    }
    if (found_timeout) {
        tv = diff_timeval(min_timestamp, current_timestamp);
        return &tv;
    } else {
        return NULL;
    }
}
Esempio n. 6
0
int main( int argc, char * * argv, char * * arg_environ )
{
    int                     n;
    char                  * s;
    struct bjam_option      optv[ N_OPTS ];
    char            const * all = "all";
    int                     status;
    int                     arg_c = argc;
    char          *       * arg_v = argv;
    char            const * progname = argv[ 0 ];
    module_t              * environ_module;

    saved_argv0 = argv[ 0 ];

    BJAM_MEM_INIT();

#ifdef OS_MAC
    InitGraf( &qd.thePort );
#endif

    --argc;
    ++argv;

    #ifdef HAVE_PYTHON
    #define OPTSTRING "-:l:m:d:j:p:f:gs:t:ano:qvz"
    #else
    #define OPTSTRING "-:l:m:d:j:p:f:gs:t:ano:qv"
    #endif

    if ( getoptions( argc, argv, OPTSTRING, optv ) < 0 )
    {
        err_printf( "\nusage: %s [ options ] targets...\n\n", progname );

        err_printf( "-a      Build all targets, even if they are current.\n" );
        err_printf( "-dx     Set the debug level to x (0-9).\n" );
        err_printf( "-fx     Read x instead of Jambase.\n" );
        /* err_printf( "-g      Build from newest sources first.\n" ); */
        err_printf( "-jx     Run up to x shell commands concurrently.\n" );
        err_printf( "-lx     Limit actions to x number of seconds after which they are stopped.\n" );
        err_printf( "-mx     Maximum target output saved (kb), default is to save all output.\n" );
        err_printf( "-n      Don't actually execute the updating actions.\n" );
        err_printf( "-ox     Mirror all output to file x.\n" );
        err_printf( "-px     x=0, pipes action stdout and stderr merged into action output.\n" );
        err_printf( "-q      Quit quickly as soon as a target fails.\n" );
        err_printf( "-sx=y   Set variable x=y, overriding environment.\n" );
        err_printf( "-tx     Rebuild x, even if it is up-to-date.\n" );
        err_printf( "-v      Print the version of jam and exit.\n" );
        #ifdef HAVE_PYTHON
        err_printf( "-z      Disable Python Optimization and enable asserts\n" );
        #endif
        err_printf( "--x     Option is ignored.\n\n" );

        exit( EXITBAD );
    }

    /* Version info. */
    if ( ( s = getoptval( optv, 'v', 0 ) ) )
    {
        out_printf( "Boost.Jam  Version %s. %s.\n", VERSION, OSMINOR );
        out_printf( "   Copyright 1993-2002 Christopher Seiwald and Perforce "
            "Software, Inc.\n" );
        out_printf( "   Copyright 2001 David Turner.\n" );
        out_printf( "   Copyright 2001-2004 David Abrahams.\n" );
        out_printf( "   Copyright 2002-2015 Rene Rivera.\n" );
        out_printf( "   Copyright 2003-2015 Vladimir Prus.\n" );
        return EXITOK;
    }

    /* Pick up interesting options. */
    if ( ( s = getoptval( optv, 'n', 0 ) ) )
    {
        ++globs.noexec;
        globs.debug[ 2 ] = 1;
    }

    if ( ( s = getoptval( optv, 'p', 0 ) ) )
    {
        /* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action
         * stdout and stderr.
         */
        globs.pipe_action = atoi( s );
        if ( globs.pipe_action < 0 || 3 < globs.pipe_action )
        {
            err_printf( "Invalid pipe descriptor '%d', valid values are -p[0..3]."
                "\n", globs.pipe_action );
            exit( EXITBAD );
        }
    }

    if ( ( s = getoptval( optv, 'q', 0 ) ) )
        globs.quitquick = 1;

    if ( ( s = getoptval( optv, 'a', 0 ) ) )
        anyhow++;

    if ( ( s = getoptval( optv, 'j', 0 ) ) )
    {
        globs.jobs = atoi( s );
        if ( globs.jobs < 1 || globs.jobs > MAXJOBS )
        {
            err_printf( "Invalid value for the '-j' option, valid values are 1 "
                "through %d.\n", MAXJOBS );
            exit( EXITBAD );
        }
    }

    if ( ( s = getoptval( optv, 'g', 0 ) ) )
        globs.newestfirst = 1;

    if ( ( s = getoptval( optv, 'l', 0 ) ) )
        globs.timeout = atoi( s );

    if ( ( s = getoptval( optv, 'm', 0 ) ) )
        globs.max_buf = atoi( s ) * 1024;  /* convert to kb */

    #ifdef HAVE_PYTHON
    if ( ( s = getoptval( optv, 'z', 0 ) ) )
        python_optimize = 0;  /* disable python optimization */
    #endif

    /* Turn on/off debugging */
    for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n )
    {
        int i;

        /* First -d, turn off defaults. */
        if ( !n )
            for ( i = 0; i < DEBUG_MAX; ++i )
                globs.debug[i] = 0;

        i = atoi( s );

        if ( ( i < 0 ) || ( i >= DEBUG_MAX ) )
        {
            out_printf( "Invalid debug level '%s'.\n", s );
            continue;
        }

        /* n turns on levels 1-n. */
        /* +n turns on level n. */
        if ( *s == '+' )
            globs.debug[ i ] = 1;
        else while ( i )
            globs.debug[ i-- ] = 1;
    }

    /* If an output file is specified, set globs.out to that. */
    if ( ( s = getoptval( optv, 'o', 0 ) ) )
    {
        if ( !( globs.out = fopen( s, "w" ) ) )
        {
            err_printf( "Failed to write to '%s'\n", s );
            exit( EXITBAD );
        }
        /* ++globs.noexec; */
    }

    constants_init();
    cwd_init();

    {
        PROFILE_ENTER( MAIN );

#ifdef HAVE_PYTHON
        {
            PROFILE_ENTER( MAIN_PYTHON );
            Py_OptimizeFlag = python_optimize;
            Py_Initialize();
            {
                static PyMethodDef BjamMethods[] = {
                    {"call", bjam_call, METH_VARARGS,
                     "Call the specified bjam rule."},
                    {"import_rule", bjam_import_rule, METH_VARARGS,
                     "Imports Python callable to bjam."},
                    {"define_action", bjam_define_action, METH_VARARGS,
                     "Defines a command line action."},
                    {"variable", bjam_variable, METH_VARARGS,
                     "Obtains a variable from bjam's global module."},
                    {"backtrace", bjam_backtrace, METH_VARARGS,
                     "Returns bjam backtrace from the last call into Python."},
                    {"caller", bjam_caller, METH_VARARGS,
                     "Returns the module from which the last call into Python is made."},
                    {NULL, NULL, 0, NULL}
                };

                Py_InitModule( "bjam", BjamMethods );
            }
            PROFILE_EXIT( MAIN_PYTHON );
        }
#endif

#ifndef NDEBUG
        run_unit_tests();
#endif
#if YYDEBUG != 0
        if ( DEBUG_PARSE )
            yydebug = 1;
#endif

        /* Set JAMDATE. */
        {
            timestamp current;
            timestamp_current( &current );
            var_set( root_module(), constant_JAMDATE, list_new( outf_time(
                &current ) ), VAR_SET );
        }

        /* Set JAM_VERSION. */
        var_set( root_module(), constant_JAM_VERSION,
                 list_push_back( list_push_back( list_new(
                   object_new( VERSION_MAJOR_SYM ) ),
                   object_new( VERSION_MINOR_SYM ) ),
                   object_new( VERSION_PATCH_SYM ) ),
                   VAR_SET );

        /* Set JAMUNAME. */
#ifdef unix
        {
            struct utsname u;

            if ( uname( &u ) >= 0 )
            {
                var_set( root_module(), constant_JAMUNAME,
                         list_push_back(
                             list_push_back(
                                 list_push_back(
                                     list_push_back(
                                         list_new(
                                            object_new( u.sysname ) ),
                                         object_new( u.nodename ) ),
                                     object_new( u.release ) ),
                                 object_new( u.version ) ),
                             object_new( u.machine ) ), VAR_SET );
            }
        }
#endif  /* unix */

        /* Set JAM_TIMESTAMP_RESOLUTION. */
        {
            timestamp fmt_resolution[ 1 ];
            file_supported_fmt_resolution( fmt_resolution );
            var_set( root_module(), constant_JAM_TIMESTAMP_RESOLUTION, list_new(
                object_new( timestamp_timestr( fmt_resolution ) ) ), VAR_SET );
        }

        /* Load up environment variables. */

        /* First into the global module, with splitting, for backward
         * compatibility.
         */
        var_defines( root_module(), use_environ, 1 );

        environ_module = bindmodule( constant_ENVIRON );
        /* Then into .ENVIRON, without splitting. */
        var_defines( environ_module, use_environ, 0 );

        /*
         * Jam defined variables OS & OSPLAT. We load them after environment, so
         * that setting OS in environment does not change Jam's notion of the
         * current platform.
         */
        var_defines( root_module(), othersyms, 1 );

        /* Load up variables set on command line. */
        for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n )
        {
            char * symv[ 2 ];
            symv[ 0 ] = s;
            symv[ 1 ] = 0;
            var_defines( root_module(), symv, 1 );
            var_defines( environ_module, symv, 0 );
        }

        /* Set the ARGV to reflect the complete list of arguments of invocation.
         */
        for ( n = 0; n < arg_c; ++n )
            var_set( root_module(), constant_ARGV, list_new( object_new(
                arg_v[ n ] ) ), VAR_APPEND );

        /* Initialize built-in rules. */
        load_builtins();

        /* Add the targets in the command line to the update list. */
        for ( n = 1; n < arg_c; ++n )
        {
            if ( arg_v[ n ][ 0 ] == '-' )
            {
                char * f = "-:l:d:j:f:gs:t:ano:qv";
                for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break;
                if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n;
            }
            else
            {
                OBJECT * const target = object_new( arg_v[ n ] );
                mark_target_for_updating( target );
                object_free( target );
            }
        }

        if ( list_empty( targets_to_update() ) )
            mark_target_for_updating( constant_all );

        /* Parse ruleset. */
        {
            FRAME frame[ 1 ];
            frame_init( frame );
            for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n )
            {
                OBJECT * const filename = object_new( s );
                parse_file( filename, frame );
                object_free( filename );
            }

            if ( !n )
                parse_file( constant_plus, frame );
        }

        status = yyanyerrors();

        /* Manually touch -t targets. */
        for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n )
        {
            OBJECT * const target = object_new( s );
            touch_target( target );
            object_free( target );
        }

        /* The build system may set the PARALLELISM variable to override -j
         * options.
         */
        {
            LIST * const p = var_get( root_module(), constant_PARALLELISM );
            if ( !list_empty( p ) )
            {
                int const j = atoi( object_str( list_front( p ) ) );
                if ( j < 1 || j > MAXJOBS )
                    out_printf( "Invalid value of PARALLELISM: %s. Valid values "
                        "are 1 through %d.\n", object_str( list_front( p ) ),
                        MAXJOBS );
                else
                    globs.jobs = j;
            }
        }

        /* KEEP_GOING overrides -q option. */
        {
            LIST * const p = var_get( root_module(), constant_KEEP_GOING );
            if ( !list_empty( p ) )
                globs.quitquick = atoi( object_str( list_front( p ) ) ) ? 0 : 1;
        }

        /* Now make target. */
        {
            PROFILE_ENTER( MAIN_MAKE );
            LIST * const targets = targets_to_update();
            if ( !list_empty( targets ) )
                status |= make( targets, anyhow );
            else
                status = last_update_now_status;
            PROFILE_EXIT( MAIN_MAKE );
        }

        PROFILE_EXIT( MAIN );
    }

    if ( DEBUG_PROFILE )
        profile_dump();


#ifdef OPT_HEADER_CACHE_EXT
    hcache_done();
#endif

    clear_targets_to_update();

    /* Widely scattered cleanup. */
    property_set_done();
    file_done();
    rules_done();
    timestamp_done();
    search_done();
    class_done();
    modules_done();
    regex_done();
    cwd_done();
    path_done();
    function_done();
    list_done();
    constants_done();
    object_done();

    /* Close log out. */
    if ( globs.out )
        fclose( globs.out );

#ifdef HAVE_PYTHON
    Py_Finalize();
#endif

    BJAM_MEM_CLOSE();

    return status ? EXITBAD : EXITOK;
}
Esempio n. 7
0
int  main( int argc, char **argv, char **arg_environ )
{
    int		n;
    char		*s;
    struct option	optv[N_OPTS];
    const char	*all = "all";
    int		anyhow = 0;
    int		status;
    int arg_c = argc;
    char ** arg_v = argv;
    const char *progname = argv[0];

# ifdef OS_MAC
    InitGraf(&qd.thePort);
# endif

    argc--, argv++;

	if( getoptions( argc, argv, "-:l:d:j:f:gs:t:ano:qv", optv ) < 0 )
    {
        printf( "\nusage: %s [ options ] targets...\n\n", progname );

        printf( "-a      Build all targets, even if they are current.\n" );
        printf( "-dx     Set the debug level to x (0-9).\n" );
        printf( "-fx     Read x instead of Jambase.\n" );
	    /* printf( "-g      Build from newest sources first.\n" ); */
        printf( "-jx     Run up to x shell commands concurrently.\n" );
        printf( "-lx     Limit actions to x number of seconds after which they are stopped.\n" );
        printf( "-n      Don't actually execute the updating actions.\n" );
        printf( "-ox     Write the updating actions to file x.\n" );
		printf( "-q      Quit quickly as soon as a target fails.\n" );
        printf( "-sx=y   Set variable x=y, overriding environment.\n" );
        printf( "-tx     Rebuild x, even if it is up-to-date.\n" );
        printf( "-v      Print the version of jam and exit.\n" );
        printf( "--x     Option is ignored.\n\n" );

        exit( EXITBAD );
    }

    /* Version info. */

    if( ( s = getoptval( optv, 'v', 0 ) ) )
    {
        printf( "Boost.Jam  " );
        printf( "Version %s. %s.\n", VERSION, OSMINOR );
	   printf( "   Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.  \n" );
        printf( "   Copyright 2001 David Turner.\n" );
        printf( "   Copyright 2001-2004 David Abrahams.\n" );
        printf( "   Copyright 2002-2005 Rene Rivera.\n" );
        printf( "   Copyright 2003-2005 Vladimir Prus.\n" );

        return EXITOK;
    }

    /* Pick up interesting options */

    if( ( s = getoptval( optv, 'n', 0 ) ) )
        globs.noexec++, globs.debug[2] = 1;

	if( ( s = getoptval( optv, 'q', 0 ) ) )
 	    globs.quitquick = 1;
    if( ( s = getoptval( optv, 'a', 0 ) ) )
        anyhow++;

    if( ( s = getoptval( optv, 'j', 0 ) ) )
        globs.jobs = atoi( s );

	if( ( s = getoptval( optv, 'g', 0 ) ) )
	    globs.newestfirst = 1;

    if( ( s = getoptval( optv, 'l', 0 ) ) )
        globs.timeout = atoi( s );

    /* Turn on/off debugging */

    for( n = 0; s = getoptval( optv, 'd', n ); n++ )
    {
        int i;

        /* First -d, turn off defaults. */

        if( !n )
            for( i = 0; i < DEBUG_MAX; i++ )
                globs.debug[i] = 0;

        i = atoi( s );

        if( i < 0 || i >= DEBUG_MAX )
        {
            printf( "Invalid debug level '%s'.\n", s );
            continue;
        }

        /* n turns on levels 1-n */
        /* +n turns on level n */

        if( *s == '+' )
            globs.debug[i] = 1;
        else while( i )
            globs.debug[i--] = 1;
    }

    { PROFILE_ENTER(MAIN);

    #ifdef HAVE_PYTHON
    {
        PROFILE_ENTER(MAIN_PYTHON);
        Py_Initialize();
    
        {
            static PyMethodDef BjamMethods[] = {
                {"call", bjam_call, METH_VARARGS,
                 "Call the specified bjam rule."},
                {"import_rule", bjam_import_rule, METH_VARARGS,
                 "Imports Python callable to bjam."},
                {NULL, NULL, 0, NULL}
            };
    
            Py_InitModule("bjam", BjamMethods);
        }
        PROFILE_EXIT(MAIN_PYTHON);
    }
    #endif
    
#ifndef NDEBUG
    run_unit_tests();
#endif
#if YYDEBUG != 0
    if ( DEBUG_PARSE )
        yydebug = 1;
#endif

    /* Set JAMDATE first */

    {
        char *date;
        time_t clock;
        time( &clock );
        date = newstr( ctime( &clock ) );

        /* Trim newline from date */

        if( strlen( date ) == 25 )
            date[ 24 ] = 0;

        var_set( "JAMDATE", list_new( L0, newstr( date ) ), VAR_SET );
    }

 
    var_set( "JAM_VERSION",
             list_new( list_new( list_new( L0, newstr( VERSION_MAJOR_SYM ) ), 
                                 newstr( VERSION_MINOR_SYM ) ), 
                       newstr( VERSION_PATCH_SYM ) ),
             VAR_SET );

    /* And JAMUNAME */
# ifdef unix
    {
        struct utsname u;

        if( uname( &u ) >= 0 )
        {
            var_set( "JAMUNAME", 
                     list_new( 
                         list_new(
                             list_new(
                                 list_new(
                                     list_new( L0, 
                                               newstr( u.sysname ) ),
                                     newstr( u.nodename ) ),
                                 newstr( u.release ) ),
                             newstr( u.version ) ),
                         newstr( u.machine ) ), VAR_SET );
        }
    }
# endif /* unix */

    /* load up environment variables */

    /* first into global module, with splitting, for backward compatibility */
    var_defines( use_environ, 1 );
    
    /* then into .ENVIRON, without splitting */
    enter_module( bindmodule(".ENVIRON") );
    var_defines( use_environ, 0 );
    exit_module( bindmodule(".ENVIRON") );

	/*
	 * Jam defined variables OS, OSPLAT
     * We load them after environment, so that
     * setting OS in environment does not 
     * change Jam notion of the current platform.
	 */

    var_defines( othersyms, 1 );


    /* Load up variables set on command line. */

    for( n = 0; s = getoptval( optv, 's', n ); n++ )
    {
        char *symv[2];
        symv[0] = s;
        symv[1] = 0;
        var_defines( symv, 1 );
    }

    /* Set the ARGV to reflect the complete list of arguments of invocation. */

    for ( n = 0; n < arg_c; ++n )
    {
        var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
    }

	/* Initialize built-in rules */

	load_builtins();

    /* Add the targets in the command line to update list */

    for ( n = 1; n < arg_c; ++n )
    {
        if ( arg_v[n][0] == '-' )
        {
            char *f = "-:l:d:j:f:gs:t:ano:qv";
            for( ; *f; f++ ) if( *f == arg_v[n][1] ) break;
            if ( f[1] == ':' && arg_v[n][2] == '\0' ) { ++n; }
        }
        else
        {
            mark_target_for_updating(arg_v[n]);
        }
    }

    /* Parse ruleset */

    {
        FRAME frame[1];
        frame_init( frame );
	for( n = 0; s = getoptval( optv, 'f', n ); n++ )
	    parse_file( s, frame );

	if( !n )
	    parse_file( "+", frame );
    }

    status = yyanyerrors();

    /* Manually touch -t targets */

    for( n = 0; s = getoptval( optv, 't', n ); n++ )
        touchtarget( s );

    /* If an output file is specified, set globs.cmdout to that */

    if( s = getoptval( optv, 'o', 0 ) )
    {
        if( !( globs.cmdout = fopen( s, "w" ) ) )
        {
            printf( "Failed to write to '%s'\n", s );
            exit( EXITBAD );
        }
        globs.noexec++;
    }

    /* Now make target */

    {
        PROFILE_ENTER(MAIN_MAKE);
        
        LIST* targets = targets_to_update();
        if ( !targets )
        {
            status |= make( 1, &all, anyhow );
        }
        else 
        {
            int targets_count = list_length(targets);
            const char **targets2 = (const char **)malloc(targets_count * sizeof(char *));
            int n = 0;
            if ( DEBUG_PROFILE )
                profile_memory( targets_count * sizeof(char *) );
            for ( ; targets; targets = list_next(targets) )
            {
                targets2[n++] = targets->string;
            }
            status |= make( targets_count, targets2, anyhow );       
            free(targets);
        }
        
        PROFILE_EXIT(MAIN_MAKE);
    }


    PROFILE_EXIT(MAIN); }
    
    if ( DEBUG_PROFILE )
        profile_dump();

    /* Widely scattered cleanup */

    var_done();
    file_done();
    donerules();
    donestamps();
    donestr();

    /* close cmdout */

    if( globs.cmdout )
        fclose( globs.cmdout );

#ifdef HAVE_PYTHON
    Py_Finalize();
#endif


    return status ? EXITBAD : EXITOK;
}