On 2022-09-01 04:35:24, Rob Landley wrote: > On 8/30/22 03:59, David Seikel wrote: > > I'm good at reading code, but I know you are not. > > As demonstrated below.
Well I had already cobbled together something that works for me, copying stuff from other parts of toybox, that largely did what you describe below. I was mostly wondering if there was some easy calltoy() type function I had missed. My cobbled together one still has a TODO to return the output. > On 8/31/22 20:33, David Seikel wrote: > > On 2022-08-31 18:18:15, enh via Toybox wrote: > >> it does by default. that's what i turned off as a workaround for this > >> bug. > > > > Um how does one using toybox as the foundation for something else > > actually call any random toy directly? Is there a vararg calltoy() > > function I missed? > > You know how we're calling xexec() everywhere? > > $ grep -l xexec main.c lib/*.c toys/*/*.c | wc -l > 30 > > That does: > > // Only recurse to builtin when we have multiplexer and !vfork context. > if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE) > if (toys.stacktop && !strchr(*argv, '/')) toy_exec(argv); > execvp(argv[0], argv); > > That first part is calling toy_exec() out of main.c, and falling back to > execvp() if it can't (or when it fails). > > There's a lot of sanity checks in toy_exec() and the things it calls, checking > if we need to re-exec to acquire SUID privileges, and measuring stack depth > and > refusing to recurse if it's gone too deep. But that's not actually required, > the > actual the actual CALL to the other command is just this bit at the end, > lightly > cleaned up to be usable out of context: > > // Run command > toy_init(toy_find(*argv), argv); > if (toys.which) { > toys.which->toy_main(); > xexit(); > } > > You could also look at main() at the end of main.c to find the standalone > init: > > // single command built standalone with no multiplexer is first list entry > toy_singleinit(toy_list, argv); > toy_list->toy_main(); > > (Using the first entry in toy_list instead of having toy_find() binary search > for a neame...) > > Or in toybox_main() there's this bit: > > char *ss = basename(s); > struct toy_list *tl = toy_find(ss); > > if (tl==toy_list && s!=toys.argv[1]) unknown(ss); > toy_exec_which(tl, toys.argv+1); > > All toy_exec() does is call toy_find() and then call toy_exec_which() with the > toy_list pointer instead of the name, but that splits them so it can add a > special error check in between to prevent "toybox toybox toybox toybox toybox > ls" from being recognized. > > I didn't think starting at "main()" or reading the xexec() implementation in > lib/ was an unreasonably high bar? There are other less obvious places you > could > have found it. > > This "which = toy_find(); toy_singleinit(which, argv); which->toy_main();" > trio > is also done manually in sh.c to implement shell builtins, but I wouldn't > expect > you to find that on a casual browse without knowing what you're looking for. > > The xpopen()/xrun() family of functions funnel into xpopen_both(), which is > also > a bit much to read (all that juggling pipes and nommu support), but it both > calls xexec() and does: > > toy_init(toys.which, toys.argv); > toys.stacktop = 0; > toys.which->toy_main(); > xexit(); > > to implement the "call ourselves again" case where argv is NULL when fork() is > available. (No toy_find() there, it re-uses the existing toys.which to just > recursively call the same command. The toys.stacktop is both to disable > further > recursion and to signal to the re-entered command that this is not the first > time it's been called, but that has to do with command reentry, ala this bit > of > cpio.c: > > if (toys.stacktop) { > // xpopen() doesn't return from child due to vfork(), instead restarts > // with !toys.stacktop > pid = xpopen(0, &pipe, 0); > afd = pipe; > } else { > // child > toys.optflags |= FLAG_i; > xchdir(*toys.optargs); > } > > Or this bit of tar.c: > > // Fork a copy of ourselves to handle extraction (reads from zip > output > // pipe, writes to stdout). > pipefd[0] = pipefd[1]; > pipefd[1] = 1; > pid = xpopen_both(0, pipefd); > close(pipefd[1]); > > (This is because nommu systems can't do fork(), and vfork() requires calling > exec() to unblock the parent, so xopen() can take a NULL argv to re-exec > ourselves, in which case the parent will have a non-null toys.stacktop when it > enters command_main() and the child will have a null one. The xpopen pipe(s) > let > the parent feed the child whatever info it needs; you can also do it through > inherited environment variables.) > > See also: > https://landley.net/toybox/code.html#running > > And: > https://landley.net/toybox/code.html#:~:text=The%20following%20functions > > Sorry I haven't done a video walkthrough of this part yet. Every time I look > at > prudetube it hits me with a fresh round of: I hate prudetube as well, and avoid it. Especially for things about coding, coz you can't copy paste text from a video. > https://youtu.be/IPXukSZhTuI > https://youtu.be/punLD6zM2bI > https://youtu.be/IdE_ADys95c > https://youtu.be/zOV1DDMenrU So I'm not clicking on whatever those are. > And I go "maybe I should find another video hosting solution"... -- A big old stinking pile of genius that no one wants coz there are too many silver coated monkeys in the world. _______________________________________________ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net