47 comments

[ 5.9 ms ] story [ 86.8 ms ] thread
This is not a complaint about the name. Just that as a command from the command line, "runc" may clash with the runc container running utility due to potential overlap in the likely users.

Again, it's not the project name just the potential clash at the OS level. Because over the years, I've done it to myself.

https://github.com/opencontainers/runc

Oh. Especially if one puts my script into ~/bin and calls '$ runc ..'

I admit I didn't research the name 'runc'.

Should I rename it ? I like this one because it's short and explicit.

yes, I would not consider using this given we use the more popular runc
You could alias it ?
What, the standard or OPs?

Why should I have to?

"compileAndRunCSource" is explicit.

People could #!bin/bash it however they want.

I only noticed the clash because "runc" seemed familiar.

instead of runc, I think ccrun would be a good name. cc is usually the c compiler so ccrun would make sense and be short and explicit.
'ccrun' is nice, thanks. 'crun' would work also.
crun is actually a project that competes with runc. runc (run container) is implemented in go, and crun is a mostly drop-in reimplementation of it in C that is more faster and simpler, it's currently gaining traction in rhel/centos/fedora and suse linux as it was first to implement newer features such as cgroup v2.
Well.. it looks like .com domains : all 4-letters taken ;)
Other ideas: execc, cexec, cmk, mkc, exc, cex (my personal favorite :p).
Compiling and running C code in a single command (without using a Makefile/build system, etc. but by pulling a binary from Homebrew or whatever) feels like a 10x engineering goal, so I therefore put forward: 10cc

As a bonus, it can output "I don't like C code, I love it" in its help/version docs.

(comment deleted)
You could rename it to "run.c" for "run dot c file." Bash supports many special characters in command names.
This looks fun. I can't imagine it being directly useful but the idea itself is fun.

Couple of immediate issues with the repo:

- Sample output in the README should not be prefixed with a "$". That's only for the shell command prompt.

- Use ``` blocks in your README file. It's easier to format multi-line text.

- Don't use $RANDOM, it's not secure. Use mktemp: https://github.com/alcover/runc/blob/73aaecea5a4cd357f7172dd...

- Don't exit with success if the command failed: https://github.com/alcover/runc/blob/73aaecea5a4cd357f7172dd...

- Use Bash strict mode: http://redsymbol.net/articles/unofficial-bash-strict-mode/

Done, done and done. Thank you !

I need a little time to study your 'strict mode' suggestion. I used 'set -e' before but had problems with it.

Would you know how I could detect that input is cat'ed into the script ? ($ cat snippet.c | runc -i). So that I can suppress 'Type your code then CTRL+D'.

re: Bash "strict mode", the shell options are fine but resetting IFS blows the weirdness budget for a default.

You can get saner splitting for that loop over the array by quoting the array expansion:

    for name in "${names[@]}"
Shellcheck lints that, by the way.
Quick and ugly alternative is chmod+x and add something like this to the top of your file:

  //$(which gcc) $0 -o a.out; ./a.out $@; rm a.out; exit
Clever polyglot file!

Does not work in the spirit of my script though, since you would still need to add headers and main():

  //$(which gcc) $0 -o a.out; ./a.out $@; rm a.out; exit
  int i = 10;
  printf ("%d\n", i);
./snip.c:3:9: error: expected declaration specifiers or ‘...’ before string constant printf ("%d\n", i);
This. My first thought was there is a UNIXy way to do this already.
This is definitely helpful for testing.

Also related is the tiny C compiler and its `tcc -run` command.

I was just about to reply about the same thing:

  #!/usr/bin/tcc -run
  
  #include <stdio.h>
  
  int main() {
    printf("Hello\n");
    return 0;
  }
Or even

  tcc -w -run - <<< 'main() { printf("Hello\n"); return 0; }'           
However, runc seems more convenient to pass in just the statements.
That wasn't quite what I was trying to show with the snippet - I was intimating that you can use tcc to run C directly in something like a shell script.

If you want to make `tcc -w -run` etc. more convenient then:

  alias trun='tcc -w -run - <<<'
  trun 'main() { printf("Hello\n"); return 0; }'
---

I can't edit my parent comment now, but it can be improved with e.g.

  //usr/bin/tcc -run $0; exit
  main() { printf("Hello\n"); return 0; }
> That wasn't quite what I was trying to show with the snippet - I was intimating that you can use tcc to run C directly in something like a shell script.

I know, but the first example in the link was:

  $ runc 'printf("%s\n", "Hello!");'  
  Hello!
So I figured I'd complement your example use with one that was more analogous to that.

> I can't edit my parent comment now, but it can be improved with e.g.

To be honest, I liked your original example more. Using that `//` "shebang" depends on what shell it's invoked from, and it wouldn't work when calling exec from other languages. For example, with your last example using `//`:

  $ python -c 'import subprocess; subprocess.run(["./hello-tcc-double-slash-shebang.c"])'   
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/usr/lib/python3.8/subprocess.py", line 489, in run
      with Popen(*popenargs, **kwargs) as process:
    File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
      self._execute_child(args, executable, preexec_fn, close_fds,
    File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
      raise child_exception_type(errno_num, err_msg, err_filename)
  OSError: [Errno 8] Exec format error: './hello-tcc-double-slash-shebang.c'
while it would work with the `#!` shebang, since that's handled by the kernel.
D has the `rdmd` command for running D code in one command.
Why is this submission submitted a day ago showing up as new again? @dang
(comment deleted)
Reminds me of [1] "c" a utility which allows you to execute C code as if it were a script. It's a shame the name is almost unsearchable in Google though...

[1] https://github.com/ryanmjacobs/c

why not just do

    gcc main.c && ./a.out
That doesn't include the headers. It also leaves a.out on your system.
What are the headers in this context that are not getting included? Shouldn't main.c include any necessary headers?
Yes, but runc includes the headers for you.
I'm sorry, I don't see the benefit of runc including a small list of headers for me. A small test program like main.c ought to be self-contained and might need headers not supplied by runc.
I mean, take it one step further then:

    gcc main.c && ./a.out && rm -f a.out
What is the big deal with just leaving the a.out alone? I might need to run it again, maybe with different arguments. A few a.out files from test programs are not exactly worth fussing over IMHO.
To each their own. If you're in vim, you don't need to leave your editor if you prepend an exclamation mark to the above expression. I often do a lot of prototyping with:

    !gcc main.c -fsanitize=address -Og && ./a.out
(comment deleted)