Exemplo n.º 1
0
int main(int argc, char const *argv[]) {
  if(argc!=2){
    printf("USAGE: %s FILE\n", argv[0]);
    return EXIT_FAILURE;
  }
  FILE* f = fopen(argv[1], "r");
  if(!f){
    perror("Failed to open file: ");
    return EXIT_FAILURE;
  }
  atexit(clean_matrix);
  yyin = f;
  yyparse();
  fclose(f);
  yylex_destroy();
  build_starts();
  link_matrix();
  struct MATRIX *matrix = get_matrix();
  int result = forkx(matrix);
  free(matrix);
  if(!result){
    wait_for_children();
  }
  return EXIT_SUCCESS;
}
Exemplo n.º 2
0
void
vsyslog(int pri, const char *fmt, va_list ap)
{
	char *b, *f, *o;
	char c;
	int clen;
	char buf[MAXLINE + 2];
	char outline[MAXLINE + 256];  /* pad to allow date, system name... */
	time_t now;
	pid_t pid;
	struct log_ctl hdr;
	struct strbuf dat;
	struct strbuf ctl;
	char timestr[26];	/* hardwired value 26 due to Posix */
	size_t taglen;
	int olderrno = errno;
	struct stat statbuff;
	int procfd;
	char procfile[32];
	psinfo_t p;
	int showpid;
	uint32_t msgid;
	char *msgid_start, *msgid_end;
	int nowait;

/*
 * Maximum tag length is 256 (the pad in outline) minus the size of the
 * other things that can go in the pad.
 */
#define	MAX_TAG		230

	/* see if we should just throw out this message */
	if (pri < 0 || PRIFAC(pri) >= LOG_NFACILITIES ||
	    (PRIMASK(pri) & LogMask) == 0)
		return;

	if (LogFileInvalid)
		return;

	/*
	 * if openlog() has not been called by the application,
	 * try to get the name of the application and set it
	 * as the ident string for messages. If unable to get
	 * it for any reason, fall back to using the default
	 * of syslog. If we succeed in getting the name, also
	 * turn on LOG_PID, to provide greater detail.
	 */
	showpid = 0;
	if (OpenLogCalled == 0) {
		(void) sprintf(procfile, "/proc/%d/psinfo", (int)getpid());
		if ((procfd = open(procfile, O_RDONLY)) >= 0) {
			if (read(procfd, &p, sizeof (psinfo_t)) >= 0) {
				(void) strncpy(ProcName, p.pr_fname, PRFNSZ);
				LogTag = (const char *) &ProcName;
				showpid = LOG_PID;
			}
			(void) close(procfd);
		}
	}
	if (LogFile < 0)
		openlog(LogTag, LogStat|LOG_NDELAY|showpid, 0);

	if ((fstat(LogFile, &statbuff) != 0) ||
	    (!S_ISCHR(statbuff.st_mode)) || (statbuff.st_rdev != LogDev)) {
		LogFileInvalid = TRUE;
		return;
	}

	/* set default facility if none specified */
	if ((pri & LOG_FACMASK) == 0)
		pri |= LogFacility;

	/* build the header */
	hdr.pri = pri;
	hdr.flags = SL_CONSOLE;
	hdr.level = 0;

	/* build the message */
	/*
	 * To avoid potential security problems, bounds checking is done
	 * on outline and buf.
	 * The following code presumes that the header information will
	 * fit in 250-odd bytes, as was accounted for in the buffer size
	 * allocation.  This is dependent on the assumption that the LogTag
	 * and the string returned by sprintf() for getpid() will return
	 * be less than 230-odd characters combined.
	 */
	o = outline;
	(void) time(&now);
	(void) sprintf(o, "%.15s ", ctime_r(&now, timestr, 26) + 4);
	o += strlen(o);

	if (LogTag) {
		taglen = strlen(LogTag) < MAX_TAG ? strlen(LogTag) : MAX_TAG;
		(void) strncpy(o, LogTag, taglen);
		o[taglen] = '\0';
		o += strlen(o);
	}
	if (LogStat & LOG_PID) {
		(void) sprintf(o, "[%d]", (int)getpid());
		o += strlen(o);
	}
	if (LogTag) {
		(void) strcpy(o, ": ");
		o += 2;
	}

	STRLOG_MAKE_MSGID(fmt, msgid);
	(void) sprintf(o, "[ID %u FACILITY_AND_PRIORITY] ", msgid);
	o += strlen(o);

	b = buf;
	f = (char *)fmt;
	while ((c = *f++) != '\0' && b < &buf[MAXLINE]) {
		char *errmsg;
		if (c != '%') {
			*b++ = c;
			continue;
		}
		if ((c = *f++) != 'm') {
			*b++ = '%';
			*b++ = c;
			continue;
		}
		if ((errmsg = strerror(olderrno)) == NULL)
			(void) snprintf(b, &buf[MAXLINE] - b, "error %d",
			    olderrno);
		else {
			while (*errmsg != '\0' && b < &buf[MAXLINE]) {
				if (*errmsg == '%') {
					(void) strcpy(b, "%%");
					b += 2;
				}
				else
					*b++ = *errmsg;
				errmsg++;
			}
			*b = '\0';
		}
		b += strlen(b);
	}
	if (b > buf && *(b-1) != '\n')	/* ensure at least one newline */
		*b++ = '\n';
	*b = '\0';
	/* LINTED variable format specifier */
	(void) vsnprintf(o, &outline[sizeof (outline)] - o, buf, ap);
	clen  = (int)strlen(outline) + 1;	/* add one for NULL byte */
	if (clen > MAXLINE) {
		clen = MAXLINE;
		outline[MAXLINE-1] = '\0';
	}

	/*
	 * 1136432 points out that the underlying log driver actually
	 * refuses to accept (ERANGE) messages longer than LOG_MAXPS
	 * bytes.  So it really doesn't make much sense to putmsg a
	 * longer message..
	 */
	if (clen > LOG_MAXPS) {
		clen = LOG_MAXPS;
		outline[LOG_MAXPS-1] = '\0';
	}

	/* set up the strbufs */
	ctl.maxlen = sizeof (struct log_ctl);
	ctl.len = sizeof (struct log_ctl);
	ctl.buf = (caddr_t)&hdr;
	dat.maxlen = sizeof (outline);
	dat.len = clen;
	dat.buf = outline;

	/* output the message to the local logger */
	if ((putmsg(LogFile, &ctl, &dat, 0) >= 0) && syslogd_ok())
		return;
	if (!(LogStat & LOG_CONS))
		return;

	/*
	 * Output the message to the console directly.  To reduce visual
	 * clutter, we strip out the message ID.
	 */
	if ((msgid_start = strstr(outline, "[ID ")) != NULL &&
	    (msgid_end = strstr(msgid_start, "] ")) != NULL)
		(void) strcpy(msgid_start, msgid_end + 2);

	clen = strlen(outline) + 1;

	nowait = (LogStat & LOG_NOWAIT);
	pid = forkx(nowait? 0 : (FORK_NOSIGCHLD | FORK_WAITPID));
	if (pid == -1)
		return;

	if (pid == 0) {
		sigset_t sigs;
		int fd;

		(void) sigset(SIGALRM, SIG_DFL);
		(void) sigemptyset(&sigs);
		(void) sigaddset(&sigs, SIGALRM);
		(void) sigprocmask(SIG_UNBLOCK, &sigs, NULL);
		(void) alarm(5);
		if (((fd = open(sysmsg, O_WRONLY)) >= 0) ||
		    (fd = open(ctty, O_WRONLY)) >= 0) {
			(void) alarm(0);
			outline[clen - 1] = '\r';
			(void) write(fd, outline, clen);
			(void) close(fd);
		}
		_exit(0);
	}
	if (!nowait)
		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
			continue;
}
Exemplo n.º 3
0
/*
 * See glibc sysdeps/unix/sysv/linux/x86_64/clone.S code for x64 argument order
 * and the Linux kernel/fork.c code for the various ways arguments can be passed
 * to the clone syscall (CONFIG_CLONE_BACKWARDS, et al).
 */
long
lx_clone(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4,
	uintptr_t p5)
{
	struct clone_state *cs;
	int flags = (int)p1;
	void *cldstk = (void *)p2;
	void *ptidp = (void *)p3;
#if defined(_LP64)
	void *ctidp = (void *)p4;
	struct lx_desc *ldtinfo = (void *)p5;
#else /* is 32bit */
	struct lx_desc *ldtinfo = (void *)p4;
	void *ctidp = (void *)p5;
#endif
	thread_t tid;
	volatile int clone_res;
	int sig;
	int rval;
	int pid;
	lx_regs_t *rp;
	sigset_t sigmask;
	int fork_flags = 0;

	if (flags & LX_CLONE_SETTLS) {
		lx_debug("lx_clone(flags=0x%x stk=0x%p ptidp=0x%p ldt=0x%p "
		    "ctidp=0x%p", flags, cldstk, ptidp, ldtinfo, ctidp);
	} else {
		lx_debug("lx_clone(flags=0x%x stk=0x%p ptidp=0x%p)",
		    flags, cldstk, ptidp);
	}

	/*
	 * Only supported for pid 0 on Linux
	 */
	if (flags & LX_CLONE_PID)
		return (-EINVAL);

	/*
	 * CLONE_THREAD requires CLONE_SIGHAND.
	 *
	 * CLONE_THREAD and CLONE_DETACHED must both be either set or cleared
	 * in kernel 2.4 and prior.
	 * In kernel 2.6 (and later) CLONE_DETACHED was dropped completely, so
	 * we no longer have this requirement.
	 */

	if (flags & CLONE_TD) {
		if (!(flags & LX_CLONE_SIGHAND))
			return (-EINVAL);
		if (strncmp(lx_release, "2.4", 3) == 0 &&
		    (flags & CLONE_TD) != CLONE_TD)
			return (-EINVAL);
	}

	rp = lx_syscall_regs();

	/* test if pointer passed by user are writable */
	if (flags & LX_CLONE_PARENT_SETTID) {
		if (uucopy(ptidp, &pid, sizeof (int)) != 0)
			return (-EFAULT);
		if (uucopy(&pid, ptidp, sizeof (int)) != 0)
			return (-EFAULT);
	}
	if (flags & LX_CLONE_CHILD_SETTID) {
		if (uucopy(ctidp, &pid, sizeof (int)) != 0)
			return (-EFAULT);
		if (uucopy(&pid, ctidp, sizeof (int)) != 0)
			return (-EFAULT);
	}

	/* See if this is a fork() operation or a thr_create().  */
	if (IS_FORK(flags) || IS_VFORK(flags)) {
		if (flags & LX_CLONE_PARENT) {
			lx_unsupported("clone(2) only supports CLONE_PARENT "
			    "for threads.\n");
			return (-ENOTSUP);
		}

		if (flags & LX_CLONE_PTRACE)
			lx_ptrace_fork();

		if ((flags & LX_CSIGNAL) == 0)
			fork_flags |= FORK_NOSIGCHLD;

		if (flags & LX_CLONE_VFORK) {
			is_vforked++;
			rval = vforkx(fork_flags);
			if (rval != 0)
				is_vforked--;
		} else {
			rval = forkx(fork_flags);
			if (rval == 0 && lx_is_rpm)
				(void) sleep(lx_rpm_delay);
		}

		/*
		 * Since we've already forked, we can't do much if uucopy
		 * fails, so we just ignore failure. Failure is unlikely since
		 * we've tested the memory before we did the fork.
		 */
		if (rval > 0 && (flags & LX_CLONE_PARENT_SETTID)) {
			(void) uucopy(&rval, ptidp, sizeof (int));
		}

		if (rval == 0 && (flags & LX_CLONE_CHILD_SETTID)) {
			/*
			 * lx_getpid should not fail, and if it does, there's
			 * not much we can do about it since we've already
			 * forked, so on failure, we just don't copy the
			 * memory.
			 */
			pid = lx_getpid();
			if (pid >= 0)
				(void) uucopy(&pid, ctidp, sizeof (int));
		}

		/* Parent just returns */
		if (rval != 0)
			return ((rval < 0) ? -errno : rval);


		/*
		 * Set up additional data in the lx_proc_data structure as
		 * necessary.
		 */
		rval = syscall(SYS_brand, B_IKE_SYSCALL + LX_EMUL_clone,
		    flags, cldstk, ptidp, ldtinfo, ctidp, NULL);
		if (rval < 0) {
			return (rval);
		}

		/*
		 * lx_setup_clone() doesn't return below, so stop now, if
		 * necessary.
		 */
		lx_ptrace_stop_if_option(LX_PTRACE_O_TRACECLONE);

		/*
		 * If provided, the child needs its new stack set up.
		 */
		if (cldstk) {
#if defined(_LP64)
			(void) syscall(SYS_brand, B_CLR_NTV_SYSC_FLAG);
			lx_setup_clone((uintptr_t)rp, (void *)rp->lxr_rip,
			    cldstk);
#else
			lx_setup_clone(rp->lxr_gs, (void *)rp->lxr_eip, cldstk);
#endif
			/* lx_setup_clone() should never return. */
			assert(0);
		}

		return (0);
	}

	/*
	 * We have very restricted support.... only exactly these flags are
	 * supported
	 */
	if (((flags & SHARED_AS) != SHARED_AS)) {
		lx_unsupported("clone(2) requires that all or none of "
		    "CLONE_VM/FS/FILES/THREAD/SIGHAND be set. (flags:0x%08X)\n",
		    flags);
		return (-ENOTSUP);
	}

	if (cldstk == NULL) {
		lx_unsupported("clone(2) requires the caller to allocate the "
		    "child's stack.\n");
		return (-ENOTSUP);
	}

	/*
	 * If we want a signal-on-exit, ensure that the signal is valid.
	 */
	if ((sig = ltos_signo[flags & LX_CSIGNAL]) == -1) {
		lx_unsupported("clone(2) passed unsupported signal: %d", sig);
		return (-ENOTSUP);
	}

	/*
	 * To avoid malloc() here, we steal a part of the new thread's
	 * stack to store all the info that thread might need for
	 * initialization.  We also make it 64-bit aligned for good
	 * measure.
	 */
	cs = (struct clone_state *)
	    ((p2 - sizeof (struct clone_state)) & -((uintptr_t)8));
	cs->c_flags = flags;
	cs->c_sig = sig;
	cs->c_stk = cldstk;
	cs->c_ptidp = ptidp;
	cs->c_ldtinfo = ldtinfo;
	cs->c_ctidp = ctidp;
	cs->c_clone_res = &clone_res;
#if defined(_LP64)
	/*
	 * The AMD64 ABI says that the kernel clobbers %rcx and %r11. We
	 * return a value in %rax. The new %rsp and %rip will be setup in
	 * lx_setup_clone. Thus, we don't worry about passing/restoring those
	 * registers.
	 */
	cs->c_regs.lxr_rdi = rp->lxr_rdi;
	cs->c_regs.lxr_rsi = rp->lxr_rsi;
	cs->c_regs.lxr_rbx = rp->lxr_rbx;
	cs->c_regs.lxr_rdx = rp->lxr_rdx;
	cs->c_regs.lxr_rdi = rp->lxr_rdi;
	cs->c_regs.lxr_r8 = rp->lxr_r8;
	cs->c_regs.lxr_r9 = rp->lxr_r9;
	cs->c_regs.lxr_r10 = rp->lxr_r10;
	cs->c_regs.lxr_r12 = rp->lxr_r12;
	cs->c_regs.lxr_r13 = rp->lxr_r13;
	cs->c_regs.lxr_r14 = rp->lxr_r14;
	cs->c_regs.lxr_r15 = rp->lxr_r15;
#else
	cs->c_gs = rp->lxr_gs;
#endif

	if (lx_sched_getaffinity(0, sizeof (cs->c_affmask),
	    (uintptr_t)&cs->c_affmask) == -1)
		lx_err_fatal("Unable to get affinity mask for parent "
		    "thread: %s", strerror(errno));

	/*
	 * We want the new thread to return directly to the return site for
	 * the system call.
	 */
#if defined(_LP64)
	cs->c_retaddr = (void *)rp->lxr_rip;
#else
	cs->c_retaddr = (void *)rp->lxr_eip;
#endif
	clone_res = 0;

	(void) sigfillset(&sigmask);

	/*
	 * Block all signals because the thread we create won't be able to
	 * properly handle them until it's fully set up.
	 */
	if (sigprocmask(SIG_BLOCK, &sigmask, &cs->c_sigmask) < 0) {
		lx_debug("lx_clone sigprocmask() failed: %s", strerror(errno));
		return (-errno);
	}

	rval = thr_create(NULL, NULL, clone_start, cs, THR_DETACHED, &tid);

	/*
	 * Release any pending signals
	 */
	(void) sigprocmask(SIG_SETMASK, &cs->c_sigmask, NULL);

	/*
	 * Wait for the child to be created and have its tid assigned.
	 */
	if (rval == 0) {
		while (clone_res == 0)
			;

		rval = clone_res;
	}

	if (rval == 0)
		lx_ptrace_stop_if_option(LX_PTRACE_O_TRACECLONE);

	return (rval);
}