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; }
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; }
/* * 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); }