summaryrefslogtreecommitdiffstats
path: root/bitbake/bin/bitbake
blob: 778b1d69eb33a4ca00bcc348d081a4c814d9325d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env python3
#
# Copyright (C) 2003, 2004  Chris Larson
# Copyright (C) 2003, 2004  Phil Blundell
# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
# Copyright (C) 2005        Holger Hans Peter Freyther
# Copyright (C) 2005        ROAD GmbH
# Copyright (C) 2006        Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#

import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)),
                                'lib'))
try:
    import bb
except RuntimeError as exc:
    sys.exit(str(exc))

from bb import cookerdata
from bb.main import bitbake_main, BitBakeConfigParameters, BBMainException

if sys.getfilesystemencoding() != "utf-8":
    sys.exit("Please use a locale setting which supports UTF-8 (such as LANG=en_US.UTF-8).\nPython can't change the filesystem locale after loading so we need a UTF-8 when Python starts or things won't work.")

__version__ = "1.43.2"

if __name__ == "__main__":
    if __version__ != bb.__version__:
        sys.exit("Bitbake core version and program version mismatch!")
    try:
        sys.exit(bitbake_main(BitBakeConfigParameters(sys.argv),
                              cookerdata.CookerConfiguration()))
    except BBMainException as err:
        sys.exit(err)
    except bb.BBHandledException:
        sys.exit(1)
    except Exception:
        import traceback
        traceback.print_exc()
        sys.exit(1)
laration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * pseudo_wrappers.c, shared code for wrapper functions
 *
 * Copyright (c) 2008-2012 Wind River Systems, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the Lesser GNU General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the Lesser GNU General Public License for more details.
 *
 * You should have received a copy of the Lesser GNU General Public License
 * version 2.1 along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 *
 */
#include <assert.h>
#include <stdlib.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <dlfcn.h>

/* include this to get PSEUDO_PORT_* definitions */
#include "pseudo.h"

/* used for various specific function arguments */
#include <dirent.h>
#include <fts.h>
#include <ftw.h>
#include <glob.h>
#include <grp.h>
#include <pwd.h>
#include <utime.h>
#ifdef PSEUDO_PORT_LINUX_STATVFS
#include <sys/statvfs.h>
#endif

#include "pseudo_wrapfuncs.h"
#include "pseudo_ipc.h"
#include "pseudo_client.h"


/* Types and declarations we need in advance. */
#include "pseudo_wrapper_table.c"

static void pseudo_enosys(const char *);
static int pseudo_check_wrappers(void);
static volatile int antimagic = 0;
static pthread_mutex_t pseudo_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t pseudo_mutex_holder;
static int pseudo_mutex_recursion = 0;
static int pseudo_getlock(void);
static void pseudo_droplock(void);
static size_t pseudo_dechroot(char *, size_t);
static void pseudo_sigblock(sigset_t *);

extern char *program_invocation_short_name;
static sigset_t pseudo_saved_sigmask;

/* Constructor only exists in libpseudo */
static void _libpseudo_init(void) __attribute__ ((constructor));

static int _libpseudo_initted = 0;

#ifdef PSEUDO_PROFILING
extern struct timeval *pseudo_wrapper_time;
/* profiling shared postamble */
#define PROFILE_START \
	struct timeval tv1, tv2; \
	do { gettimeofday(&tv1, NULL); } while(0)
#define PROFILE_DONE do { \
	gettimeofday(&tv2, NULL); \
	pseudo_wrapper_time->tv_sec += tv2.tv_sec - tv1.tv_sec; \
	pseudo_wrapper_time->tv_usec += tv2.tv_usec - tv1.tv_usec; } while(0)
#else
#define PROFILE_START do {} while(0)
#define PROFILE_DONE do {} while(0)
#endif

/* later, the init code can change these to refer to the real calls and
 * skip the wrappers.
 */
#ifdef PSEUDO_XATTRDB
extern ssize_t (*pseudo_real_lgetxattr)(const char *, const char *, void *, size_t);
extern ssize_t (*pseudo_real_fgetxattr)(int, const char *, void *, size_t);
extern int (*pseudo_real_lsetxattr)(const char *, const char *, const void *, size_t, int);
extern int (*pseudo_real_fsetxattr)(int, const char *, const void *, size_t, int);
#endif

static void libpseudo_atfork_child(void)
{
	pthread_mutex_init(&pseudo_mutex, NULL);
	pseudo_mutex_recursion = 0;
	pseudo_mutex_holder = 0;
}

static void
_libpseudo_init(void) {
	if (!_libpseudo_initted)
		pthread_atfork(NULL, NULL, libpseudo_atfork_child);

	pseudo_getlock();
	pseudo_antimagic();
	_libpseudo_initted = 1;

	pseudo_init_util();
	pseudo_init_wrappers();
	pseudo_init_client();

	pseudo_magic();
	pseudo_droplock();
}

void
pseudo_reinit_libpseudo(void) {
	_libpseudo_init();
}

static void
pseudo_init_one_wrapper(pseudo_function *func) {
	int (*f)(void) = (int (*)(void)) NULL;

	if (*func->real != NULL) {
		/* already initialized */
		return;
	}
	dlerror();

#if PSEUDO_PORT_LINUX
	if (func->version)
		f = dlvsym(RTLD_NEXT, func->name, func->version);
	/* fall through to the general case, if that failed */
	if (!f)
#endif
	f = dlsym(RTLD_NEXT, func->name);
	if (f) {
		*func->real = f;
	}
	/* it turns out that in some cases, we get apparently-harmless
	 * errors if a function is missing, and that printing output
	 * for these seems unhelpful. so we no longer do that.
	 */
}

void
pseudo_init_wrappers(void) {
	int i;
	static int done = 0;

	pseudo_getlock();
	pseudo_antimagic();

	/* We only ever want to run this once, even though we might want to
	 * "re-init" at specific times...
	 */
	if (!done) {
		for (i = 0; pseudo_functions[i].name; ++i) {
			pseudo_init_one_wrapper(&pseudo_functions[i]);
		}
		done = 1;
	}

#ifdef PSEUDO_XATTRDB
	pseudo_real_lgetxattr = real_lgetxattr;
	pseudo_real_fgetxattr = real_fgetxattr;
	pseudo_real_lsetxattr = real_lsetxattr;
	pseudo_real_fsetxattr = real_fsetxattr;
#endif
	pseudo_real_lstat = base_lstat;
	/* bash has its own local copies of these which it uses
	 * instead of ours...
	 */
	pseudo_real_unsetenv = dlsym(RTLD_NEXT, "unsetenv");
	pseudo_real_getenv = dlsym(RTLD_NEXT, "getenv");
	pseudo_real_setenv = dlsym(RTLD_NEXT, "setenv");
	/* and these are used so the client's server spawn can bypass
	 * wrappers.
	 */
	pseudo_real_fork = dlsym(RTLD_NEXT, "fork");
	pseudo_real_execv = dlsym(RTLD_NEXT, "execv");

	/* Once the wrappers are setup, we can now use open... so
	 * setup the logfile, if necessary...
	 */
	pseudo_debug_logfile(NULL, -1);

	pseudo_magic();
	pseudo_droplock();
}

static void
pseudo_sigblock(sigset_t *saved) {
	sigset_t blocked;

	/* these are signals for which the handlers often
	 * invoke operations, such as close(), which are handled
	 * by pseudo and could result in a deadlock.
	 */
	sigemptyset(&blocked);
	sigaddset(&blocked, SIGALRM);	/* every-N-seconds tasks */
	sigaddset(&blocked, SIGCHLD);	/* reaping child processes */
	sigaddset(&blocked, SIGHUP);	/* idiomatically, reloading config */
	sigaddset(&blocked, SIGTERM);	/* shutdown/teardown operations */
	sigaddset(&blocked, SIGUSR1);	/* reopening log files, sometimes */
	sigaddset(&blocked, SIGUSR2);	/* who knows what people do */
	sigprocmask(SIG_BLOCK, &blocked, saved);
}

static int
pseudo_getlock(void) {
	if (pthread_equal(pseudo_mutex_holder, pthread_self())) {
		++pseudo_mutex_recursion;
		return 0;
	} else {
		if (pthread_mutex_lock(&pseudo_mutex) == 0) {
			pseudo_mutex_recursion = 1;
			pseudo_mutex_holder = pthread_self();
			return 0;
		} else {
			return -1;
		}
	}
}

static void
pseudo_droplock(void) {
	if (--pseudo_mutex_recursion == 0) {
		pseudo_mutex_holder = 0;
		pthread_mutex_unlock(&pseudo_mutex);
	}
}

void
pseudo_antimagic() {
	++antimagic;
}

void
pseudo_magic() {
	if (antimagic > 0)
		--antimagic;
}

static void
pseudo_enosys(const char *func) {
	pseudo_diag("pseudo: ENOSYS for '%s'.\n", func ? func : "<nil>");
	char * value = pseudo_get_value("PSEUDO_ENOSYS_ABORT");
	if (value)
		abort();
	free(value);
	errno = ENOSYS;
}

/* de-chroot a string.
 * note that readlink() yields an unterminated buffer, so
 * must pass in the correct length.  Buffers are null-terminated
 * unconditionally if they are modified -- the modification would
 * shorten the string, so there will be space for the NUL, so
 * this is safe even for stuff like readlink().
 */
static size_t
pseudo_dechroot(char *s, size_t len) {
	if (len == (size_t) -1)
		len = strlen(s);
	if (pseudo_chroot_len && len >= pseudo_chroot_len &&
		!memcmp(s, pseudo_chroot, pseudo_chroot_len)) {
		if (s[pseudo_chroot_len] == '/') {
			memmove(s, s + pseudo_chroot_len, len - pseudo_chroot_len);
			len -= pseudo_chroot_len;
			s[len] = '\0';
		} else if (s[pseudo_chroot_len] == '\0') {
			s[0] = '/';
			len = 1;
			s[len] = '\0';
		}
		/* otherwise, it's not really a match... */
	}
	return len;
}

static int
pseudo_check_wrappers(void) {
	if (!_libpseudo_initted)
		pseudo_reinit_libpseudo();

	return _libpseudo_initted;
}		

/* the generated code goes here */
#include "port_wrappers.c"
#include "pseudo_wrapfuncs.c"