orbea / cross / slibtool

Forked from cross/slibtool 3 years ago
Clone

Blame src/helper/slbt_dump_machine.c

575cdb
/*******************************************************************/
575cdb
/*  slibtool: a skinny libtool implementation, written in C        */
6803d8
/*  Copyright (C) 2016--2018  Z. Gilboa                            */
575cdb
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
575cdb
/*******************************************************************/
575cdb
575cdb
#include <stdio.h>
575cdb
#include <limits.h>
575cdb
#include <unistd.h>
575cdb
#include <fcntl.h>
575cdb
#include <string.h>
575cdb
#include <stdlib.h>
575cdb
#include <stdbool.h>
575cdb
#include <sys/wait.h>
575cdb
575cdb
#include <slibtool/slibtool.h>
575cdb
#include "slibtool_spawn_impl.h"
575cdb
d986a0
static void slbt_dump_machine_child(
575cdb
	char *	program,
575cdb
	int	fd[2])
575cdb
{
575cdb
	char *	compiler;
575cdb
	char *	argv[3];
575cdb
db27dd
	close(fd[0]);
db27dd
f7d56b
	if ((compiler = strrchr(program,'/')))
575cdb
		compiler++;
575cdb
	else
575cdb
		compiler = program;
575cdb
575cdb
	argv[0] = compiler;
575cdb
	argv[1] = "-dumpmachine";
575cdb
	argv[2] = 0;
575cdb
f4ed8e
	if ((fd[0] = open("/dev/null",O_RDONLY)) >= 0)
f4ed8e
		if (dup2(fd[0],0) == 0)
f4ed8e
			if (dup2(fd[1],1) == 1)
f4ed8e
				execvp(program,argv);
575cdb
ec6d7a
	_exit(EXIT_FAILURE);
575cdb
}
575cdb
575cdb
int slbt_dump_machine(
575cdb
	const char *	compiler,
575cdb
	char *		machine,
db27dd
	size_t		buflen)
575cdb
{
db27dd
	int	ret;
575cdb
	pid_t	pid;
575cdb
	pid_t	rpid;
575cdb
	int	code;
575cdb
	int	fd[2];
c67e64
	char *	mark;
575cdb
	char	program[PATH_MAX];
575cdb
db27dd
	/* setup */
db27dd
	if (!machine || !--buflen) {
db27dd
		errno = EINVAL;
575cdb
		return -1;
db27dd
	}
575cdb
575cdb
	if ((size_t)snprintf(program,sizeof(program),"%s",
575cdb
			compiler) >= sizeof(program))
575cdb
		return -1;
575cdb
db27dd
	/* fork */
575cdb
	if (pipe(fd))
575cdb
		return -1;
575cdb
575cdb
	if ((pid = fork()) < 0) {
575cdb
		close(fd[0]);
575cdb
		close(fd[1]);
575cdb
		return -1;
575cdb
	}
575cdb
db27dd
	/* child */
575cdb
	if (pid == 0)
d986a0
		slbt_dump_machine_child(
575cdb
			program,
575cdb
			fd);
575cdb
db27dd
	/* parent */
db27dd
	close(fd[1]);
db27dd
db27dd
	mark = machine;
db27dd
db27dd
	for (; buflen; ) {
db27dd
		ret = read(fd[0],mark,buflen);
db27dd
db27dd
		while ((ret < 0) && (errno == EINTR))
db27dd
			ret = read(fd[0],mark,buflen);
db27dd
db27dd
		if (ret > 0) {
db27dd
			buflen -= ret;
db27dd
			mark   += ret;
db27dd
db27dd
		} else if (ret == 0) {
db27dd
			close(fd[0]);
db27dd
			buflen = 0;
db27dd
db27dd
		} else {
db27dd
			close(fd[0]);
db27dd
			return ret;
db27dd
		}
db27dd
	}
db27dd
db27dd
	/* execve verification */
575cdb
	rpid = waitpid(
575cdb
		pid,
575cdb
		&code,
575cdb
		0);
575cdb
575cdb
	if ((rpid != pid) || code) {
db27dd
		errno = EBADR;
575cdb
		return -1;
575cdb
	}
575cdb
db27dd
	/* newline verification */
db27dd
	if ((mark == machine) || (*--mark != '\n')) {
db27dd
		errno = EBADR;
db27dd
		return -1;
575cdb
	}
575cdb
db27dd
	*mark = 0;
db27dd
db27dd
	/* portbld <--> unknown synonym? */
db27dd
	if ((mark = strstr(machine,"-portbld-")))
db27dd
		memcpy(mark,"-unknown",8);
c67e64
db27dd
	/* all done */
db27dd
	return 0;
575cdb
}