Ejemplo n.º 1
0
// PCA These calls to debug are rather sketchy because they may allocate memory. Fortunately they only occur if an error occurs.
int set_child_group(job_t *j, process_t *p, int print_errors)
{
    int res = 0;

    if (job_get_flag(j, JOB_CONTROL))
    {
        if (!j->pgid)
        {
            j->pgid = p->pid;
        }

        if (setpgid(p->pid, j->pgid))
        {
            if (getpgid(p->pid) != j->pgid && print_errors)
            {
                char pid_buff[128];
                char job_id_buff[128];
                char getpgid_buff[128];
                char job_pgid_buff[128];

                format_long_safe(pid_buff, p->pid);
                format_long_safe(job_id_buff, j->job_id);
                format_long_safe(getpgid_buff, getpgid(p->pid));
                format_long_safe(job_pgid_buff, j->pgid);

                debug_safe(1,
                           "Could not send process %s, '%s' in job %s, '%s' from group %s to group %s",
                           pid_buff,
                           p->argv0_cstr(),
                           job_id_buff,
                           j->command_cstr(),
                           getpgid_buff,
                           job_pgid_buff);

                safe_perror("setpgid");
                res = -1;
            }
        }
    }
    else
    {
        j->pgid = getpid();
    }

    if (job_get_flag(j, JOB_TERMINAL) && job_get_flag(j, JOB_FOREGROUND))
    {
        if (tcsetpgrp(0, j->pgid) && print_errors)
        {
            char job_id_buff[128];
            format_long_safe(job_id_buff, j->job_id);
            debug_safe(1, "Could not send job %s ('%s') to foreground", job_id_buff, j->command_cstr());
            safe_perror("tcsetpgrp");
            res = -1;
        }
    }

    return res;
}
Ejemplo n.º 2
0
/**
   This function is a wrapper around fork. If the fork calls fails
   with EAGAIN, it is retried FORK_LAPS times, with a very slight
   delay between each lap. If fork fails even then, the process will
   exit with an error message.
*/
pid_t execute_fork(bool wait_for_threads_to_die)
{
    ASSERT_IS_MAIN_THREAD();

    if (wait_for_threads_to_die || JOIN_THREADS_BEFORE_FORK)
    {
        /* Make sure we have no outstanding threads before we fork. This is a pretty sketchy thing to do here, both because exec.cpp shouldn't have to know about iothreads, and because the completion handlers may do unexpected things. */
        iothread_drain_all();
    }

    pid_t pid;
    struct timespec pollint;
    int i;

    g_fork_count++;

    for (i=0; i<FORK_LAPS; i++)
    {
        pid = fork();
        if (pid >= 0)
        {
            return pid;
        }

        if (errno != EAGAIN)
        {
            break;
        }

        pollint.tv_sec = 0;
        pollint.tv_nsec = FORK_SLEEP_TIME;

        /*
          Don't sleep on the final lap - sleeping might change the
          value of errno, which will break the error reporting below.
        */
        if (i != FORK_LAPS-1)
        {
            nanosleep(&pollint, NULL);
        }
    }

    debug_safe(0, FORK_ERROR);
    safe_perror("fork");
    FATAL_EXIT();
    return 0;
}
Ejemplo n.º 3
0
/** Make sure the fd used by each redirection is not used by a pipe. Note that while this does not modify the vector, it does modify the IO redirections within (gulp) */
static void free_redirected_fds_from_pipes(const io_chain_t &io_chain)
{
    size_t max = io_chain.size();
    for (size_t i = 0; i < max; i++)
    {
        int fd_to_free = io_chain.at(i)->fd;

        /* We only have to worry about fds beyond the three standard ones */
        if (fd_to_free <= 2)
            continue;

        /* Make sure the fd is not used by a pipe */
        for (size_t j = 0; j < max; j++)
        {
            /* We're only interested in pipes */
            io_data_t *io = io_chain.at(j).get();
            if (io->io_mode != IO_PIPE && io->io_mode != IO_BUFFER)
                continue;

            CAST_INIT(io_pipe_t *, possible_conflict, io);
            /* If the pipe is a conflict, dup it to some other value */
            for (int k=0; k<2; k++)
            {
                /* If it's not a conflict, we don't care */
                if (possible_conflict->pipe_fd[k] != fd_to_free)
                    continue;

                /* Repeat until we have a replacement fd */
                int replacement_fd = -1;
                while (replacement_fd < 0)
                {
                    replacement_fd = dup(fd_to_free);
                    if (replacement_fd == -1 && errno != EINTR)
                    {
                        debug_safe_int(1, FD_ERROR, fd_to_free);
                        safe_perror("dup");
                        FATAL_EXIT();
                    }
                }
                possible_conflict->pipe_fd[k] = replacement_fd;
            }
        }
    }
}
Ejemplo n.º 4
0
/// Perform output from builtins. May be called from a forked child, so don't do anything that may
/// allocate memory, etc.
bool do_builtin_io(const char *out, size_t outlen, const char *err, size_t errlen) {
    bool success = true;
    if (out && outlen) {
        if (write_loop(STDOUT_FILENO, out, outlen) < 0) {
            int e = errno;
            debug_safe(0, "Error while writing to stdout");
            safe_perror("write_loop");
            success = false;
            errno = e;
        }
    }

    if (err && errlen) {
        if (write_loop(STDERR_FILENO, err, errlen) < 0) {
            success = false;
        }
    }
    return success;
}
Ejemplo n.º 5
0
/**
   Set up a childs io redirections. Should only be called by
   setup_child_process(). Does the following: First it closes any open
   file descriptors not related to the child by calling
   close_unused_internal_pipes() and closing the universal variable
   server file descriptor. It then goes on to perform all the
   redirections described by \c io.

   \param io the list of IO redirections for the child

   \return 0 on sucess, -1 on failiure
*/
static int handle_child_io(const io_chain_t &io_chain)
{
    for (size_t idx = 0; idx < io_chain.size(); idx++)
    {
        const io_data_t *io = io_chain.at(idx).get();
        int tmp;

        if (io->io_mode == IO_FD && io->fd == static_cast<const io_fd_t*>(io)->old_fd)
        {
            continue;
        }

        switch (io->io_mode)
        {
            case IO_CLOSE:
            {
                if (log_redirections) fprintf(stderr, "%d: close %d\n", getpid(), io->fd);
                if (close(io->fd))
                {
                    debug_safe_int(0, "Failed to close file descriptor %s", io->fd);
                    safe_perror("close");
                }
                break;
            }

            case IO_FILE:
            {
                // Here we definitely do not want to set CLO_EXEC because our child needs access
                CAST_INIT(const io_file_t *, io_file, io);
                if ((tmp=open(io_file->filename_cstr,
                              io_file->flags, OPEN_MASK))==-1)
                {
                    if ((io_file->flags & O_EXCL) &&
                            (errno ==EEXIST))
                    {
                        debug_safe(1, NOCLOB_ERROR, io_file->filename_cstr);
                    }
                    else
                    {
                        debug_safe(1, FILE_ERROR, io_file->filename_cstr);
                        safe_perror("open");
                    }

                    return -1;
                }
                else if (tmp != io->fd)
                {
                    /*
                      This call will sometimes fail, but that is ok,
                      this is just a precausion.
                    */
                    close(io->fd);

                    if (dup2(tmp, io->fd) == -1)
                    {
                        debug_safe_int(1,  FD_ERROR, io->fd);
                        safe_perror("dup2");
                        return -1;
                    }
                    exec_close(tmp);
                }
                break;
            }

            case IO_FD:
            {
                int old_fd = static_cast<const io_fd_t *>(io)->old_fd;
                if (log_redirections) fprintf(stderr, "%d: fd dup %d to %d\n", getpid(), old_fd, io->fd);

                /*
                  This call will sometimes fail, but that is ok,
                  this is just a precausion.
                */
                close(io->fd);


                if (dup2(old_fd, io->fd) == -1)
                {
                    debug_safe_int(1, FD_ERROR, io->fd);
                    safe_perror("dup2");
                    return -1;
                }
                break;
            }

            case IO_BUFFER:
            case IO_PIPE:
            {
                CAST_INIT(const io_pipe_t *, io_pipe, io);
                /* If write_pipe_idx is 0, it means we're connecting to the read end (first pipe fd). If it's 1, we're connecting to the write end (second pipe fd). */
                unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1);
                /*
                        debug( 0,
                             L"%ls %ls on fd %d (%d %d)",
                             write_pipe?L"write":L"read",
                             (io->io_mode == IO_BUFFER)?L"buffer":L"pipe",
                             io->fd,
                             io->pipe_fd[0],
                             io->pipe_fd[1]);
                */
                if (log_redirections) fprintf(stderr, "%d: %s dup %d to %d\n", getpid(), io->io_mode == IO_BUFFER ? "buffer" : "pipe", io_pipe->pipe_fd[write_pipe_idx], io->fd);
                if (dup2(io_pipe->pipe_fd[write_pipe_idx], io->fd) != io->fd)
                {
                    debug_safe(1, LOCAL_PIPE_ERROR);
                    safe_perror("dup2");
                    return -1;
                }

                if (io_pipe->pipe_fd[0] >= 0)
                    exec_close(io_pipe->pipe_fd[0]);
                if (io_pipe->pipe_fd[1] >= 0)
                    exec_close(io_pipe->pipe_fd[1]);
                break;
            }

        }
    }

    return 0;

}
Ejemplo n.º 6
0
int
BSP_i2c_initialize(void)
{
int busno, succ = 0;

	/* Initialize the library */
	if ( rtems_libi2c_initialize() ) {
		safe_printf("Initializing I2C library failed\n");
		return -1;
	}

	/* Register our bus driver */
	if ( (busno=rtems_libi2c_register_bus(
					BSP_I2C_BUS0_NAME,
					BSP_I2C_BUS_DESCRIPTOR) ) < 0 ) {
		safe_perror("Registering mpc8540 i2c bus driver");
		return -1;
	}

	/* Now register higher level drivers; note that
	 * the i2c address in the manual is actually left-shifted
	 * by one bit, i.e., as it would go on the bus.
	 */

	/* Use read-only driver for VPD */
	if ( rtems_libi2c_register_drv(
				BSP_I2C_VPD_EEPROM_NAME,
				i2c_2b_eeprom_ro_driver_descriptor,
				busno,
				BSP_VPD_I2C_ADDR) < 0 ) {
		safe_perror("Registering i2c VPD eeprom driver failed");
	} else {
		succ++;
	}

	/* Use read-write driver for user eeprom -- you still might
	 * have to disable HW write-protection on your board.
	 */
	if ( rtems_libi2c_register_drv(
				BSP_I2C_USR_EEPROM_NAME,
				i2c_2b_eeprom_driver_descriptor,
				busno,
				BSP_USR0_I2C_ADDR) < 0 ) {
		safe_perror("Registering i2c 1st USR eeprom driver failed");
	} else {
		succ++;
	}

	/* Use read-write driver for user eeprom -- you still might
	 * have to disable HW write-protection on your board.
	 */
	if ( rtems_libi2c_register_drv(
				BSP_I2C_USR1_EEPROM_NAME,
				i2c_2b_eeprom_driver_descriptor,
				busno,
				BSP_USR1_I2C_ADDR) < 0 ) {
		safe_perror("Registering i2c 2nd USR eeprom driver failed");
	} else {
		succ++;
	}

	/* The thermostat */
	if ( rtems_libi2c_register_drv(
				BSP_I2C_DS1621_NAME,
				i2c_ds1621_driver_descriptor,
				busno,
				BSP_THM_I2C_ADDR) < 0 ) {
		safe_perror("Registering i2c ds1621 temp sensor. driver failed");
	} else {
		succ++;
	}

	/* Finally, as an example, register raw access to the
	 * ds1621. The driver above just reads the 8 msb of the
	 * temperature but doesn't support anything else. Using
	 * the raw device node you can write/read individual
	 * control bytes yourself and e.g., program the thermostat...
	 */

	if ( mknod(
			BSP_I2C_DS1621_RAW_DEV_NAME,
			0666 | S_IFCHR,
			rtems_filesystem_make_dev_t(rtems_libi2c_major,
				  RTEMS_LIBI2C_MAKE_MINOR(busno,BSP_THM_I2C_ADDR))) ) {
		safe_perror("Creating device node for raw ds1621 (temp. sensor) access failed");
	} else {
		succ++;
	}

	/* Raw access to RTC */
	if ( mknod(
			BSP_I2C_DS1375_RAW_DEV_NAME,
			0666 | S_IFCHR,
			rtems_filesystem_make_dev_t(rtems_libi2c_major,
				  RTEMS_LIBI2C_MAKE_MINOR(busno,BSP_RTC_I2C_ADDR))) ) {
		safe_perror("Creating device node for raw ds1375 (rtc) access failed");
	} else {
		succ++;
	}

	safe_printf("%i I2C devices registered\n", succ);
	return 0;
}