Compile and execute C "scripts" in one go!

Overview

c

"There isn't much that's special about C. That's one of the reasons why it's fast."

I love C for its raw speed (although it does have its drawbacks). We should all write more C.

With this shell script, you can compile and execute C "scripts" in one go!

(Oh yeah, and it works for C++ too.)

GIF Demo

Here's a simple example:

#include <stdio.h>

int main(void) {
    printf("Hello World!\n");
    return 0;
}

Run it by typing:

$ c hello.c
Hello World!

Or, call it from the shebang!

#!/usr/bin/c
#include <stdio.h>

int main(void) {
    printf("Hello World!\n");
    return 0;
}
$ chmod +x hello.c
$ ./hello.c
Hello World!

Hooked? Here's how to install it:

Use a package manager? Check here.

For the entire system:

$ wget https://raw.githubusercontent.com/ryanmjacobs/c/master/c
$ sudo install -m 755 c /usr/bin/c

# Or... for systems that prefer /usr/local/bin (e.g. macOS)
$ sudo install -m 755 c /usr/local/bin/c

For your local user only:

$ wget https://raw.githubusercontent.com/ryanmjacobs/c/master/c
$ sudo install -Dm 755 c ~/.bin/c
$ echo 'PATH=$PATH:$HOME/.bin' >> ~/.bashrc

Note: if you install it somewhere other than /usr/bin/c, then your shebang will be different. For example it may be something more similar to #!/home/ryan/.bin/c.

Okay, how do I use it?

c will use whatever $CC is set to. You can change this with:

$ export CC=clang
$ export CC=tcc
$ # etc...

CLI

Multiple Files - CLI

Anything you want passed to the compiler, put in quotes as the first argument. Whether they're flags (-Wall, -O2, etc.) or file names (file.c, main.c, etc.).

$ c "main.c other.c" arg1 arg2
$ c "main.c other.c -O3 -Wall -lncurses" arg1 arg2

Single File - CLI

With only one file, omit the quotes:

$ c hello.c
$ c main.c arg1 arg2

Shebang!

After adding a shebang, just set the file to executable and it's ready to run.

$ chmod +x file.c
$ ./file.c

Single File - Shebang

Add this to the top of your C file:

#!/usr/bin/c

Multiple Files - Shebang

Just tack on any extra flags, options, or files you want passed to the compiler. Then be sure to add the terminating -- characters.

#!/usr/bin/c file1.c file2.c -lncurses -lm --

Caching

The default cache size is set to 5 MB. You can change this with:

$ export C_CACHE_SIZE=$((10*1024)) # 10 MB

The default cache path is set to $TMPDIR/c.cache. You can change this with:

$ export C_CACHE_PATH="/tmp/the_cache"

Contributing

Feel free to submit any ideas, questions, or problems by reporting an issue. Or, if you're feeling a bit brave, submit a pull request. 😬

Just hack away and make sure that all the tests pass.

$ cd tests
$ ./test.sh

Why?

First of all, I want to clarify why this is not the same as tcc -run. TCC is a compiler. We all know that. TCC will perform its own set of optimizations, just as GCC will perform its own and Clang will perform its own. The purpose of this script is to give a simple front-end to your favorite compiler.

Whether it's GCC, Clang, or something else entirely, you get to choose your compiler.

Second reason: it's simply satisfying to type c hello.c and see it run instantly.

Third reason: I'm a fan of speed, and C definitely offers it. Being able to write a small, fast, and portable C "script" is great. You can pass around a C "script" just like you would a BASH script.

zsh

If you're using zsh, then you can take advantage of zsh's suffix aliases:

$ alias -s c='c'
$ alias -s cc='c'
$ alias -s cpp='c'

Then you can run files with ./file.c without chmod +x.

Packages

Use a package manager? You've come to the right place.

AUR: https://aur.archlinux.org/packages/c/
bpkg: bpkg install ryanmjacobs/c
brew: brew install https://raw.githubusercontent.com/ryanmjacobs/c/master/c.rb (shebang will be #!/usr/local/bin/c)

Todo

Maybe later we can implement caching. Done!

License

MIT License.

Basically, you can do whatever you want provided that you include the LICENSE notice in any copy of the source. Also, I am not liable if the script breaks anything.

Issues
  • Related work

    Related work

    Hi @ryanmjacobs,

    I just want to mention similar work. You might consider adding a link to your readme or taking inspiration from the ~/.c99shrc config file.

    • https://github.com/RhysU/c99sh
    • Other nice C stuff: https://notabug.org/koz.ross/awesome-c# (You might want to add your project to the list)
    opened by slowkow 14
  • sed for shebang fails on OSX

    sed for shebang fails on OSX

    The sed command that removes/replaces the shebang appears to fail on OSX yosemite:

    $ c << EOF
    #include <stdio.h>
    
    int main()
    {
      printf("Hello World!\n");
      return 0;
    }
    EOF
    sed: 1: "/tmp/c.ox3.stdin.c": command c expects \ followed by text
    Hello World!
    sed: 1: "/tmp/c.ox3.stdin.c": command c expects \ followed by text
    
    opened by jasonkeene 11
  • Does not work in paths containing spaces

    Does not work in paths containing spaces

    The script does not work on files with paths containing whitespaces.

    [[email protected] my folder]$ pwd
    /home/jimmy/my folder
    [[email protected] my folder]$ ./foo.c 
    cc: error: folder: No such file or directory
    [[email protected] my folder]$ c foo.c
    cc: error: folder: No such file or directory
    [[email protected] my folder]$ c "/home/jimmy/my folder/foo.c"
    cc: error: /home/jimmy/my: No such file or directory
    cc: error: folder/foo.c: No such file or directory
    cc: error: folder: No such file or directory
    cc: fatal error: no input files
    compilation terminated.
    
    opened by Kwarf 7
  • GNU/BSD sed compatibility

    GNU/BSD sed compatibility

    We need a command that doesn't require gnu-sed to be installed with brew.

    This should work on both GNU and BSD systems:

    $ cat > file.c
    #!/usr/bin/c blah blah blah
    ^D
    $ sed -i.bak '1!b;s/^#!/\/\/#!/' file.c
    $ cat file.c
    //#!/usr/bin/c blah blah blah
    

    However, I don't have access to a BSD system... It works just fine on GNU. Can someone confirm that it works on BSD systems, too? Thanks.

    opened by ryanmjacobs 6
  • For users that don't have -Dm for install

    For users that don't have -Dm for install

    On Mac High Sierra, it's worth noting that -Dm is not considered as an option for the install tool. I'm not sure about other versions, but I think its worth putting in the extra lines I have to avoid confusion.

    opened by gh0std3v 4
  • Programs with stdin redirection/piping

    Programs with stdin redirection/piping

    Currently we can't pipe stdin input into a C program, e.g.

    #include <stdio.h>
    
    int main(void) {
        char buf[1024];
        while (fgets(buf, 1024, stdin) != NULL) {
            puts(buf);
        }
    }
    
    $ c file.c arg1 arg2 < /dev/urandom
    $ ./file.c arg1 arg2 < /dev/urandom
    

    Because we use stdin for file input, I don't think we can also use it for program input as well. I'm not quite sure how to approach this... maybe we can only choose one or the other?

    (btw, stdin input without piping works just fine)

    $ c file.c arg1 arg2
    hello
    hello
    
    world
    world
    
    ^C
    
    opened by ryanmjacobs 4
  • -D option isn't present on BSD `install`, causing bpkg install to fail on some systems

    -D option isn't present on BSD `install`, causing bpkg install to fail on some systems

    BSD install doesn't have the -D option, which causes installation to fail on systems that use this version of install.

    My (probably incomplete) understanding is that this can be resolved by splitting this into a mkdir -p followed by install sans the -D option, but I don't know if there is a better way that works with the bpkg 'install' field.

    For reference, the relevant install command: https://github.com/ryanmjacobs/c/blob/master/package.json#L6

    opened by xwmx 3
  • Added caching support

    Added caching support

    This pull request implements caching support. Cache size is controlled through the $cachesize variable, and older entries are deleted upon running cleanup. Cache locations are determined by hashing the file contents and compile options using sha1, appending them onto one long string and then subsequently hashing the result to fit into a filename.

    Enjoy your speed boosts! :)

    opened by souramoo 3
  • Move license file out into separate file

    Move license file out into separate file

    Having the license in the same file as the readme makes this more difficult to package than it needs to be., as I would need to manually parse the readme file. If the license was in a separate file, I could just copy it into place.

    opened by djmattyg007 3
  • Suggestion: Mention the use of #!/usr/bin/env c to launch script.

    Suggestion: Mention the use of #!/usr/bin/env c to launch script.

    !/usr/bin/env c

    At the top of the script searches your path for 'c' and execute that script.

    Means you can use it no matter where your 'c' is installed (~/bin/ /usr/local/bin or /usr/bin et al).

    opened by nashidau 3
  • Reading shebang in comment

    Reading shebang in comment

    In my Emacs config, I have clang-format do most of my formatting.

    Adding a shebang: #!/usr/bin/c -Wall -Wextra -Werror seems to mess with the formatter.

    Perhaps it might be possible to put the shebang in a comment:

    // #!/usr/bin/c -Wall -Wextra -Werror
    

    and have c look for it with regex: ^\/\/[\s]?#!.*?

    opened by chrisalcantara 2
  • 多文件问题

    多文件问题

    [email protected]:/mnt/c/Users/niuyuling/Desktop/libini# ../c/c test.c -L./ -lini -static /usr/bin/ld: /tmp/cc3AcSun.o: in function main': test.c:(.text.startup+0x21): undefined reference togetinikeystring' /usr/bin/ld: test.c:(.text.startup+0x5f): undefined reference to getinikeystring' /usr/bin/ld: test.c:(.text.startup+0x9a): undefined reference togetinikeyint' /usr/bin/ld: test.c:(.text.startup+0xdd): undefined reference to getinikeylong' /usr/bin/ld: test.c:(.text.startup+0x121): undefined reference togetinikeyfloat' /usr/bin/ld: test.c:(.text.startup+0x170): undefined reference to putinikeystring' /usr/bin/ld: test.c:(.text.startup+0x18d): undefined reference togetinikeystring' /usr/bin/ld: test.c:(.text.startup+0x1cd): undefined reference to `getinikeystring' collect2: error: ld returned 1 exit status [email protected]:/mnt/c/Users/niuyuling/Desktop/libini#

    [email protected]:/mnt/c/Users/niuyuling/Desktop/libini# ../c/c 'test.c -L./ -lini -static' /usr/bin/ld: 找不到 -lini collect2: error: ld returned 1 exit status [email protected]:/mnt/c/Users/niuyuling/Desktop/libini#

    可不可以支持多文件或者链接库文件 Can I support multiple files or link library files?

    opened by niuyuling 1
  • A better shebang

    A better shebang

    A better "shebang" would be

    ///bin/true; /usr/bin/c "$0" "$*"; exit $?
    

    as it would keep file compileable with normal gcc invocation. See example of this here (also discussion on StackOverflow).

    opened by yugr 0
  • Cheaper and faster prehash generation mechanism

    Cheaper and faster prehash generation mechanism

    I am not sure if you have much interest in this, but I found that this method of creating id is no less reliable and faster as well as cheaper.

    I must admit I have not done exhaustive testing, but if you find this interesting I am happy to do a good bit more validation. In my limited testing it has been reliable.

    Ran a few comparisons just so there's something I can show. The only difference is this changeset.

    These are my two test scripts...

    #!/bin/sh
    echo "*** Run 1000 iterations new method ***"
    for i in `seq 0 999`; do
        /home/ubuntu/bin/c.new "redis-h1get.c -ggdb -Wall -I/usr/include/hiredis `pkg-config --libs --cflags hiredis`" h1 tags > /dev/null
    done
    echo "*** Done running new method ***"
    
    #!/bin/sh
    echo "*** Run 1000 iterations original method ***"
    for i in `seq 0 999`; do
        /home/ubuntu/bin/c "redis-h1get.c -ggdb -Wall -I/usr/include/hiredis `pkg-config --libs --cflags hiredis`" h1 tags > /dev/null
    done
    echo "*** Done original method ***"
    
    *** Run 1000 iterations new method ***
    *** Done running new method ***
    3.56user 6.32system 0:38.73elapsed 25%CPU (0avgtext+0avgdata 3280maxresident)k
    0inputs+16000outputs (0major+2885064minor)pagefaults 0swaps
    
    *** Run 1000 iterations new method ***
    *** Done running new method ***
    3.48user 6.51system 0:38.55elapsed 25%CPU (0avgtext+0avgdata 3304maxresident)k
    0inputs+16000outputs (0major+2890112minor)pagefaults 0swaps
    
    
    *** Run 1000 iterations original method ***
    *** Done original method ***
    17.10user 19.30system 1:02.29elapsed 58%CPU (0avgtext+0avgdata 8440maxresident)k
    0inputs+112000outputs (0major+3196581minor)pagefaults 0swaps
    
    *** Run 1000 iterations original method ***
    *** Done original method ***
    16.76user 20.06system 1:01.91elapsed 59%CPU (0avgtext+0avgdata 8420maxresident)k
    0inputs+112000outputs (0major+3196095minor)pagefaults 0swaps
    

    Thanks!

    opened by szaydel 5
Releases(v0.14)
Owner
Ryan Jacobs
Ryan Jacobs
Remote Download and Memory Execute for shellcode framework

RmExecute Remote Download and Memory Execute for shellcode framework 远程下载并内存加载的ShellCode框架,暂不支持X64 参(抄)考(袭)项目 windows下shellcode提取模板的实现 主要抄袭来源,直接使用这位大佬

null 38 Jun 26, 2022
Isaac ROS common utilities and scripts for use in conjunction with the Isaac ROS suite of packages.

Isaac ROS Common Isaac ROS common utilities and scripts for use in conjunction with the Isaac ROS suite of packages. Docker Scripts run_dev.sh creates

NVIDIA Isaac ROS 41 Jul 1, 2022
C-shellcode to hex converter, handy tool for paste & execute shellcodes in gdb, windbg, radare2, ollydbg, x64dbg, immunity debugger & 010 editor

shellex WARNING: the ugliest code in the world C-shellcode to hex converter. Handy tool for paste & execute shellcodes in gdb, windbg, radare2, ollydb

David Reguera Garcia aka Dreg 79 Jun 20, 2022
Hijack Printconfig.dll to execute shellcode

printjacker Printjacker is a post-exploitation tool that creates a persistence mechanism by overwriting Printconfig.dll with a shellcode injector. The

Red Section 82 Jun 10, 2022
A tool for generating build scripts for C++20 projects that use modules.

cpp_module_parser [cmop] A tool for generating build scripts for C++20 projects that use modules. The intent is to provide a backend for premake, for

Alexander Christensen 2 Nov 23, 2021
a compile-time, header-only, dimensional analysis and unit conversion library built on c++14 with no dependencies.

UNITS A compile-time, header-only, dimensional analysis library built on c++14 with no dependencies. Get in touch If you are using units.h in producti

Nic Holthaus 761 Jun 14, 2022
cavi is an open-source library that aims to provide performant utilities for closed hierarchies (i.e. all class types of the hierarchy are known at compile time).

cavi cavi is an open-source library that aims to provide performant utilities for closed hierarchies (i.e. all class types of the hierarchy are known

Baber Nawaz 5 Mar 9, 2022
featured cs:go internal hack, one file and less than 1000 lines.

singlefile This is a featured CS:GO internal cheat written in less than 1000 lines, and in one C++ file. I encourage you to submit feature suggestions

null 46 Mar 2, 2022
Do u wanna create more than one trial account on exitlag? This 'spoofer' is for you!

ExitLag HWID Bypass Do you wanna create more than one trial account on exitlag? So this 'spoofer' is for you! Why? Exitlag limit the trial account cre

Benjamin 10 Mar 6, 2021
Header-only lock-free synchronization utilities (one writer, many readers).

stupid Header-only lock-free synchronization utilities (one writer, many readers). No queues Base functionality The base functionality of this library

Colugo 13 Jun 9, 2022
CommonMark parsing and rendering library and program in C

cmark cmark is the C reference implementation of CommonMark, a rationalized version of Markdown syntax with a spec. (For the JavaScript reference impl

CommonMark 1.3k Jun 25, 2022
libcurses and dependencies taken from netbsd and brought into a portable shape (at least to musl or glibc)

netbsd-libcurses portable edition this is a port of netbsd's curses library for usage on Linux systems (tested and developed on sabotage linux, based

null 119 Jun 19, 2022
Sqrt OS is a simulation of an OS scheduler and memory manager using different scheduling algorithms including Highest Priority First (non-preemptive), Shortest Remaining Time Next, and Round Robin.

A CPU scheduler determines an order for the execution of its scheduled processes; it decides which process will run according to a certain data structure that keeps track of the processes in the system and their status. A process, upon creation, has one of the three states: Running, Ready, Blocked (doing I/O, using other resources than CPU or waiting on unavailable resource).

Abdallah Hemdan 18 Apr 15, 2022
The lightweight and modern Map SDK for Android and iOS

Open Mobile Maps The lightweight and modern Map SDK for Android (6.0+) and iOS (10+) openmobilemaps.io Getting started Readme Android Readme iOS Featu

Open Mobile Maps 90 Jun 13, 2022
Indexes points and lines and generates map tiles to display them

Datamaps This is a tool for indexing large lists of geographic points or lines and dynamically generating map tiles from the index for display. Depend

Eric Fischer 328 Jun 16, 2022
A LKM rootkit targeting 4.x and 5.x kernel versions which opens a backdoor that can be used to spawn a reverse shell to a remote host and more.

Umbra Umbra (/ˈʌmbrə/) is an experimental LKM rootkit for kernels 4.x and 5.x (up to 5.7) which opens a network backdoor that spawns reverse shells to

Marcos S. Bajo 77 Jul 3, 2022
A cross-platform OpenXR capabilities explorer and runtime switcher with a CLI and GUI.

OpenXR Explorer OpenXR Explorer is a handy debug tool for OpenXR developers. It allows for easy switching between OpenXR runtimes, shows lists of the

Nick Klingensmith 116 Jun 26, 2022
Simple and lightweight pathname parser for C. This module helps to parse dirname, basename, filename and file extension .

Path Module For C File name and extension parsing functionality are removed because it's difficult to distinguish between a hidden dir (ex: .git) and

Prajwal Chapagain 3 Feb 25, 2022
A shebang-friendly script for "interpreting" single C99, C11, and C++ files, including rcfile support.

c99sh Basic Idea Control Files Shebang Tricks C++ C11 Credits Basic Idea A shebang-friendly script for "interpreting" single C99, C11, and C++ files,

Rhys Ulerich 100 Jun 9, 2022