/* <value to be concatenated onto named parameter> . */ void o_catassign (memel *argp) { char *pname = (char *) argp; char *pk, *t, *p, *f; char s1[1024+1]; struct operand o1, o2; struct param *pp; breakout (pname, &pk, &t, &p, &f); pp = paramsrch (pk, t, p); paramget (pp, *f); /* If param value is undefined merely assign into it, otherwise * concatenate operand to current value. */ o1 = popop(); if (!opundef(&o1)) { /* Must copy string value off of operand stack or the next * pushop below will reuse the space! */ o2 = popop(); strncpy (s1, o2.o_val.v_s, 1024); s1[1024] = EOS; o2.o_val.v_s = s1; pushop (&o1); pushop (&o2); binop (OP_CONCAT); } paramset (pp, *f); pp->p_flags |= P_SET; }
void o_doaddpipe (memel *argp) { XINT getpipe_pc = *argp; char *x1, *pk, *t, *x2; char *ltname; struct operand o; struct ltask *ltp; char *addpipe(); /* ADDPIPE is called immediately before REDIR and before EXEC so we * do not have to worry about storing the pipefile name in the dict. * Our argument is the PC of the GETPIPE instruction, the args field * of which is the taskname of the second task in the pipe. If either * the new task (first task in the pipe) or the second task is a * FOREIGN task, the pipe must be created as a text file. */ ltname = (char *)&(coderef(getpipe_pc)->c_args); if (*ltname == '$') ltname++; breakout (ltname, &x1, &pk, &t, &x2); ltp = cmdsrch (pk, t); binpipe = ((ltp == NULL || !(ltp->lt_flags & LT_FOREIGN)) && !(newtask->t_flags & T_FOREIGN)); if (binpipe) newtask->t_flags |= T_STDOUTB; o.o_type = OT_STRING; o.o_val.v_s = comdstr (addpipe()); pushop (&o); }
/* . * given the name of a parameter, print it on t_out, the task pipe channel. */ void o_inspect (memel *argp) { char *pname = (char *) argp; char *pk, *t, *p, *f; struct param *pp; struct operand o; breakout (pname, &pk, &t, &p, &f); pp = paramsrch (pk, t, p); if (*f == FN_NULL && (pp->p_type & PT_LIST)) { /* Hitting EOF from a list is ok during an inspect stmt so * avoid using paramget() with its EOF error. * readlist() may set P_LEOF. */ o = readlist (pp); if ((pp->p_flags & P_LEOF) || inrange (pp, &o)) pushop (&o); else query (pp); } else validparamget (pp, *f); o = popop(); if (cldebug && (o.o_type & OT_BASIC) == OT_STRING) eprintf ("Inspect--%s\n", o.o_val.v_s); prop (&o); tprintf ("\n"); }
void o_swon (memel *argp) { register char *pname = (char *)argp; register struct param *pp; struct pfile *pfp; struct operand o; char *pk, *t, *p, *f; breakout (pname, &pk, &t, &p, &f); if (*pk) cl_error (E_UERR, e_simplep, p); pfp = newtask->t_pfp; pp = ppfind (pfp, t, p, 0, NO); if (pp == NULL) cl_error (E_UERR, e_pnonexist, p); if ((XINT)pp == ERR) cl_error (E_UERR, e_pambig, p, newtask->t_ltp->lt_lname); o.o_type = OT_BOOL; o.o_val.v_i = YES; pushop (&o); paramset (pp, FN_VALUE); if (pp->p_type & PT_PSET) psetreload (pfp, pp); pp->p_flags |= P_CLSET; }
int main( int argc, char **argv, char **envp) { unsigned long i; char *input, *output; struct arch *archs; unsigned long narchs; progname = argv[0]; input = NULL; output = NULL; archs = NULL; narchs = 0; for(i = 1; i < argc; i++){ if(strcmp(argv[i], "-o") == 0){ if(i + 1 == argc){ error("missing argument(s) to: %s option", argv[i]); usage(); } if(output != NULL){ error("more than one: %s option specified", argv[i]); usage(); } output = argv[i+1]; i++; } else{ if(input != NULL){ error("more than one input file specified (%s and %s)", argv[i], input); usage(); } input = argv[i]; } } if(input == NULL || output == NULL) usage(); breakout(input, &archs, &narchs, FALSE); if(errors) exit(EXIT_FAILURE); checkout(archs, narchs); process(archs, narchs); writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE); if(errors) return(EXIT_FAILURE); else return(EXIT_SUCCESS); }
/* . <value of parameter> */ void o_pushparam (memel *argp) { char *pname = (char *) argp; char *pk, *t, *p, *f; struct param *pp; breakout (pname, &pk, &t, &p, &f); pp = paramsrch (pk, t, p); validparamget (pp, *f); }
/* <new value for named parameter> . */ void o_assign (memel *argp) { char *pname = (char *) argp; char *pk, *t, *p, *f; struct param *pp; breakout (pname, &pk, &t, &p, &f); pp = paramsrch (pk, t, p); paramset (pp, *f); pp->p_flags |= P_SET; }
/* <string operand> . * if argument to which we are assigning is a simple string or filename (or * list, since assigning to a list sets a filename too), set it to o_val.v_s, * else use o_val.v_s as the name of a parameter and use its value as the name * of the variable, that is, do an indirect through o_val.v_s. * compiled when the parser sees a simple identifier, not in an expression. * this avoids quotes around simple strings and filenames. * if the parameter is to be fake, make it type string and do not do the * indirection. */ void o_indirabsset (memel *argp) { char *argname = (char *) argp; char *pk, *t, *p, *f; struct pfile *pfp; struct param *pp; int type, string_len; pfp = newtask->t_pfp; if (pfp->pf_flags & PF_FAKE) { struct operand o; o = popop(); string_len = strlen (o.o_val.v_s); pp = newfakeparam (pfp, argname, 0, OT_STRING, string_len); f = argname; *f = FN_NULL; pushop (&o); } else { breakout (argname, &pk, &t, &p, &f); if (*pk) cl_error (E_UERR, e_simplep, p); pp = ppfind (pfp, t, p, 0, NO); if (pp == NULL) cl_error (E_UERR, e_pnonexist, p); if ((XINT)pp == ERR) cl_error (E_UERR, e_pambig, p, pfp->pf_ltp->lt_lname); } /* lone identifiers are treated as strings, rather than variables, * if the corresponding parameter is a simple string, filename or list. * note that fakeparams are made as strings. */ type = pp->p_type; if (type & (PT_FILNAM|PT_LIST|PT_PSET)) { struct operand o; o = popop(); pushop (&o); } else if ((type & OT_BASIC) != OT_STRING || type & (PT_STRUCT|PT_IMCUR|PT_GCUR|PT_UKEY)) { opindir(); /* replace top op with value of o_val.v_s */ } paramset (pp, *f); if (pp->p_type & PT_PSET) psetreload (pfp, pp); pp->p_flags |= P_CLSET; }
/* <value to be divided into named parameter> . */ void o_divassign (memel *argp) { char *pname = (char *) argp; char *pk, *t, *p, *f; struct param *pp; struct operand o1, o2; breakout (pname, &pk, &t, &p, &f); pp = paramsrch (pk, t, p); validparamget (pp, *f); /* get param value on stack */ o1 = popop(); /* swap operands */ o2 = popop(); pushop (&o1); pushop (&o2); binop (OP_DIV); /* perform the division */ paramset (pp, *f); pp->p_flags |= P_SET; }
/* <value to be subtracted from named parameter> . */ void o_subassign (memel *argp) { /* operands are backwards on stack, so negate and add. can get by * with this as long as subtraction is never defined for strings. * if it is someday, will have to do something like in addassign. */ char *pname = (char *) argp; char *pk, *t, *p, *f; struct param *pp; breakout (pname, &pk, &t, &p, &f); pp = paramsrch (pk, t, p); unop (OP_MINUS); validparamget (pp, *f); binop (OP_ADD); paramset (pp, *f); pp->p_flags |= P_SET; }
/* <increment to be added to named parameter> . */ void o_addassign (memel *argp) { /* order of operands will be incorrect. * strictly speaking, only strings are not commutative but we need * to pop both operands anyway to check. */ char *pname = (char *) argp; char *pk, *t, *p, *f; struct param *pp; struct operand o1, o2; breakout (pname, &pk, &t, &p, &f); pp = paramsrch (pk, t, p); validparamget (pp, *f); o1 = popop(); o2 = popop(); if ((o2.o_type & OT_BASIC) == OT_STRING) { /* copy o2 onto dictionary to avoid overwriting it on stack * when o1 is pushed. we can get by with not worrying about o1 * as long as whatever code copies the string works when the * strings overlap. */ XINT oldtopd = topd; char *s2 = memneed (btoi (strlen (o2.o_val.v_s) + 1)); strcpy (s2, o2.o_val.v_s); o2.o_val.v_s = s2; pushop (&o1); pushop (&o2); topd = oldtopd; /* discard temp string area */ } else { pushop (&o1); pushop (&o2); } binop (OP_ADD); paramset (pp, *f); pp->p_flags |= P_SET; }
/* <new value for named argument> . * Assign the top operand to the named parameter. Also, make the type of the * fake parameter the same as the type of the operand. */ void o_absargset (memel *argp) { char *argname = (char *) argp; char *pk, *t, *p, *f; struct pfile *pfp; struct param *pp; pfp = newtask->t_pfp; if (pfp->pf_flags & PF_FAKE) { /* use full argname and always assign to value field. */ struct operand o; int string_len=0; o = popop(); if ((o.o_type & OT_BASIC) == OT_STRING) string_len = strlen (o.o_val.v_s); pp = newfakeparam (pfp, argname, 0, o.o_type, string_len); pushop (&o); f = argname; *f = FN_NULL; } else { breakout (argname, &pk, &t, &p, &f); if (*pk) cl_error (E_UERR, e_simplep, p); pp = ppfind (pfp, t, p, 0, NO); if (pp == NULL) cl_error (E_UERR, e_pnonexist, p); if ((XINT)pp == ERR) cl_error (E_UERR, e_pambig, p, pfp->pf_ltp->lt_lname); } paramset (pp, *f); if (pp->p_type & PT_PSET) psetreload (pfp, pp); pp->p_flags |= P_CLSET; }
/* * The seg_hack(1) program changes all segments names to the one specified on * the command line: * seg_hack NEWSEGNAME input -o output */ int main( int argc, char **argv, char **envp) { int i; char *input, *output; struct arch *archs; unsigned long narchs; struct stat stat_buf; progname = argv[0]; input = NULL; output = NULL; archs = NULL; narchs = 0; if(argc < 3){ usage(); return(EXIT_FAILURE); } segname = argv[1]; for(i = 2; i < argc; i++){ if(strcmp(argv[i], "-o") == 0){ if(i + 1 == argc){ error("missing argument(s) to: %s option", argv[i]); usage(); } if(output != NULL){ error("more than one: %s option specified", argv[i]); usage(); } output = argv[i+1]; i++; } else{ if(input != NULL){ error("more than one input file specified (%s and %s)", argv[i], input); usage(); } input = argv[i]; } } if(input == NULL || output == NULL) usage(); breakout(input, &archs, &narchs, FALSE); if(errors) return(EXIT_FAILURE); process(archs, narchs); /* create the output file */ if(stat(input, &stat_buf) == -1) system_error("can't stat input file: %s", input); writeout(archs, narchs, output, stat_buf.st_mode & 0777, TRUE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); else return(EXIT_SUCCESS); }
/* * The codesign_allocate(1) tool has the following usage: * * codesign_allocate -i oldfile -a arch size ... -o newfile * * Where the oldfile is a Mach-O file that is input for the dynamic linker * and it creates or adds an */ int main( int argc, char **argv, char **envp) { uint32_t i; char *input, *output, *endp; struct arch *archs; uint32_t narchs; progname = argv[0]; input = NULL; output = NULL; archs = NULL; narchs = 0; for(i = 1; i < argc; i++) { if(strcmp(argv[i], "-i") == 0) { if(i + 1 == argc) { error("missing argument to: %s option", argv[i]); usage(); } if(input != NULL) { error("more than one: %s option specified", argv[i]); usage(); } input = argv[i+1]; i++; } else if(strcmp(argv[i], "-o") == 0) { if(i + 1 == argc) { error("missing argument to: %s option", argv[i]); usage(); } if(output != NULL) { error("more than one: %s option specified", argv[i]); usage(); } output = argv[i+1]; i++; } else if(strcmp(argv[i], "-a") == 0) { if(i + 2 == argc) { error("missing argument(s) to: %s option", argv[i]); usage(); } else { arch_signs = reallocate(arch_signs, (narch_signs + 1) * sizeof(struct arch_sign)); if(get_arch_from_flag(argv[i+1], &(arch_signs[narch_signs].arch_flag)) == 0) { error("unknown architecture specification flag: " "%s %s %s", argv[i], argv[i+1], argv[i+2]); arch_usage(); usage(); } arch_signs[narch_signs].datasize = strtoul(argv[i+2], &endp, 0); if(*endp != '\0') fatal("size for '-a %s %s' not a proper number", argv[i+1], argv[i+2]); if((arch_signs[narch_signs].datasize % 16) != 0) fatal("size for '-a %s %s' not a multiple of 16", argv[i+1], argv[i+2]); arch_signs[narch_signs].found = FALSE; narch_signs++; i += 2; } } else if(strcmp(argv[i], "-A") == 0) { if(i + 3 == argc) { error("missing argument(s) to: %s option", argv[i]); usage(); } else { arch_signs = reallocate(arch_signs, (narch_signs + 1) * sizeof(struct arch_sign)); arch_signs[narch_signs].arch_flag.cputype = strtoul(argv[i+1], &endp, 0); if(*endp != '\0') fatal("cputype for '-A %s %s %s' not a proper number", argv[i+1], argv[i+2], argv[i+3]); arch_signs[narch_signs].arch_flag.cpusubtype = strtoul(argv[i+2], &endp, 0); if(*endp != '\0') fatal("cpusubtype for '-A %s %s %s' not a proper " "number", argv[i+1], argv[i+2], argv[i+3]); arch_signs[narch_signs].arch_flag.name = (char *) get_arch_name_from_types( arch_signs[narch_signs].arch_flag.cputype, arch_signs[narch_signs].arch_flag.cpusubtype); arch_signs[narch_signs].datasize = strtoul(argv[i+3], &endp, 0); if(*endp != '\0') fatal("size for '-A %s %s %s' not a proper number", argv[i+1], argv[i+2], argv[i+3]); if((arch_signs[narch_signs].datasize % 16) != 0) fatal("size for '-A %s %s %s' not a multiple of 16", argv[i+1], argv[i+2], argv[i+3]); arch_signs[narch_signs].found = FALSE; narch_signs++; i += 3; } } else { error("unknown flag: %s", argv[i]); usage(); } } if(input == NULL || output == NULL || narch_signs == 0) usage(); breakout(input, &archs, &narchs, FALSE); if(errors) exit(EXIT_FAILURE); checkout(archs, narchs); process(archs, narchs); for(i = 0; i < narch_signs; i++) { if(arch_signs[i].found == FALSE) fatal("input file: %s does not contain a matching architecture " "for specified '-a %s %u' option", input, arch_signs[i].arch_flag.name, arch_signs[i].datasize); } writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); else return(EXIT_SUCCESS); }
/* * The ctf_insert(1) tool has the following usage: * * ctf_insert input -arch arch ctf_file ... -o output * * Where the input is a Mach-O file that is the ctf_file(s) are to be inserted * into and output is the file to be created. */ int main( int argc, char **argv, char **envp) { uint32_t i; char *input, *output, *contents; struct arch *archs; uint32_t narchs; struct stat stat_buf; int fd; progname = argv[0]; input = NULL; output = NULL; archs = NULL; narchs = 0; for(i = 1; i < argc; i++){ if(strcmp(argv[i], "-o") == 0){ if(i + 1 == argc){ error("missing argument to: %s option", argv[i]); usage(); } if(output != NULL){ error("more than one: %s option specified", argv[i]); usage(); } output = argv[i+1]; i++; } else if(strcmp(argv[i], "-arch") == 0){ if(i + 2 == argc){ error("missing argument(s) to: %s option", argv[i]); usage(); } else{ arch_ctfs = reallocate(arch_ctfs, (narch_ctfs + 1) * sizeof(struct arch_ctf)); if(get_arch_from_flag(argv[i+1], &(arch_ctfs[narch_ctfs].arch_flag)) == 0){ error("unknown architecture specification flag: " "%s %s %s", argv[i], argv[i+1], argv[i+2]); arch_usage(); usage(); } if((fd = open(argv[i+2], O_RDONLY, 0)) == -1) system_fatal("can't open file: %s", argv[i+2]); if(fstat(fd, &stat_buf) == -1) system_fatal("can't stat file: %s", argv[i+2]); /* * For some reason mapping files with zero size fails * so it has to be handled specially. */ contents = NULL; if(stat_buf.st_size != 0){ contents = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0); if((intptr_t)contents == -1) system_error("can't map file : %s", argv[i+2]); } arch_ctfs[narch_ctfs].filename = argv[i+2]; arch_ctfs[narch_ctfs].contents = contents; arch_ctfs[narch_ctfs].size = stat_buf.st_size; arch_ctfs[narch_ctfs].arch_found = FALSE; narch_ctfs++; i += 2; } } else{ if(input != NULL){ error("more than one input file file: %s specified", input); usage(); } input = argv[i]; } } if(input == NULL || output == NULL || narch_ctfs == 0) usage(); breakout(input, &archs, &narchs, FALSE); if(errors) exit(EXIT_FAILURE); checkout(archs, narchs); process(archs, narchs); for(i = 0; i < narch_ctfs; i++){ if(arch_ctfs[i].arch_found == FALSE) fatal("input file: %s does not contain a matching architecture " "for specified '-arch %s %s' option", input, arch_ctfs[i].arch_flag.name, arch_ctfs[i].filename); } writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, FALSE, NULL); if(errors) return(EXIT_FAILURE); else return(EXIT_SUCCESS); }
/* CALLNEWTASK -- Called from CALL instruction to push and setup a new task * structure. If find a known ltask with given name create a new task on * control stack, set up newtask and defaults for the pseudofiles. * Pseudofiles may be effected by other instructions before it gets to exec. * Make sure we have a pfile list; either try to read it if task is * supposed to have a real one or manufacture the beginnings of one if it * isn't and set PF_FAKE. New task runs with a copy of the pfile if it * wasn't fake. Guard against making more than one copy. Also, don't dup * the cl's params to maintain the meaning of "firstask". Things like mode, * logfile and abbreviations should be global and permanent. * Special case for package names essentially runs a cl but with a new curpack, * the only real semantic intent of "running" a package. * This lets a package name given as a command appear to change the current * package and yet remain interactive. Since it really is a new task, state * saving and restoring on error will work right and we also achieve an * ability to have multiple package defn's in a script ltask. * Any parameter references will refer to the cl's also. */ void callnewtask ( char *name ) { /* x1 and x2 are just place holders to call breakout(). */ char *x1, *pk, *t, *x2; struct ltask *ltp; int flags, ltflags; if (cldebug) eprintf ("callnewtask: name=%s, currentask=%x\n", name, currentask); /* Save current dictionary and stack pointers. they get restored when * the new task dies normally and the current task is to continue. * save pc when get to the EXEC instruction so it continues from there. */ currentask->t_topos = topos; /* save these two just in case */ currentask->t_basos = basos; /* something is left on the stk */ currentask->t_topcs = topcs; /* save before adding newtask */ currentask->t_topd = topd; /* save before adding pfile */ currentask->t_curpack = curpack;/* save in case changing to a new one*/ c_envmark (¤task->t_envp);/* save env stack pointer */ currentask->t_pno = 0; /* set only if task defines pkg */ newtask = pushtask(); flags = 0; /* Search for the command to run. A leading '$' signifies that * execution is to be time but is not part of the name. Set ltp * and newtask->t_pfp depending on whether we are running a task or * a package. */ if (*name == '$') { flags |= T_TIMEIT; name++; } breakout (name, &x1, &pk, &t, &x2); ltp = cmdsrch (pk, t); if (ltp->lt_flags & LT_CL) { /* Change curpack if LT_PACCL. (cmdsrch() set lt_pkp). Just * changing packages; use cl's ltask and pfile. Push a new cl() * on the control stack, with the T_PKGCL and T_CL flags set. */ if (ltp->lt_flags & LT_PACCL) { flags |= T_PKGCL; curpack = ltp->lt_pkp; } else if (ltp->lt_flags & LT_CLEOF) flags |= T_CLEOF; ltp = firstask->t_ltp; newtask->t_pfp = firstask->t_pfp; /* Initialize the lexical analyzer (necessary to recognize BOL). */ lexinit(); } else { if (ltp->lt_flags & LT_PFILE) { register struct pfile *pfp; /* This task has a real pfile. read in if not already in * core. Copy if not already one and not just cl. */ newtask->t_pfp = NULL; if ((pfp = pfilefind (ltp)) == NULL) pfp = pfileload (ltp); if (!(pfp->pf_flags & PF_COPY) && ltp != firstask->t_ltp) pfp = pfilecopy (pfp); newtask->t_pfp = pfp; /* Also load any pset files associated with the main pfile. * These are linked into a list with the main pfile at the * head of the list, pointed to by the task descriptor. */ if (pfp->pf_flags & PF_PSETREF) { register struct param *pp; struct operand o; char *pset; for (pp = pfp->pf_pp; pp != NULL; pp = pp->p_np) { if (!(pp->p_type & PT_PSET)) continue; o = pp->p_valo; if (opundef(&o) || *(pset = o.o_val.v_s) == EOS) pset = pp->p_name; pfp = pfp->pf_npset = pfilecopy (pfilesrch (pset)); pfp->pf_psetp = pp; } } } else { /* This task does not have a real pfile so start a fake one. */ newtask->t_pfp = newpfile (ltp); newtask->t_pfp->pf_flags = PF_FAKE; } } newtask->t_pfp->pf_n = 0; /* init number of command line args */ newtask->t_ltp = ltp; newtask->t_pid = -1; /* gets set if do a real exec */ newtask->t_stdin = currentask->t_stdin; /* inherit files */ newtask->t_stdout = currentask->t_stdout; newtask->t_stderr = currentask->t_stderr; newtask->t_stdgraph = currentask->t_stdgraph; newtask->t_stdimage = currentask->t_stdimage; newtask->t_stdplot = currentask->t_stdplot; /* Init i/o redirection for a foreign task. */ newtask->ft_in = newtask->ft_out = newtask->ft_err = NULL; /* Set up flags describing the kind of task we are about to run. the * absence of any of these flags will imply a genuine executable task. * the flags in t_flags are more of a convenience than anything since * later tests could use the same tests used here. */ ltflags = ltp->lt_flags; if (ltflags & LT_PSET) { flags = (T_SCRIPT|T_PSET); } else if (ltflags & LT_SCRIPT) { newtask->t_scriptln = 0; flags = T_SCRIPT; } else if (ltflags & LT_FOREIGN) { flags = T_BUILTIN | T_FOREIGN; /* a type of builtin */ } else if (ltflags & LT_BUILTIN) { flags = T_BUILTIN; } else if (ltflags & LT_CL) { /* Or, not assign: preserve T_PKGCL and T_CLEOF flags if set. */ flags |= T_CL; } if (ltflags & LT_STDINB) flags |= T_STDINB; if (ltflags & LT_STDOUTB) flags |= T_STDOUTB; newtask->t_flags = flags; }