11 ms·
Kirc – A tiny IRC client written in POSIX C99
- messe 6y agoThis has probably a repeat of what would have been said a decade ago about c89/c99, but why use c99 over c11?
- chriszhang 6y agoNot trying to be snarky. Honest question: Why use C11 over C99? Or even why use C99 over C89? What significant advantages do the new standards provide that cannot be done in plain old C89?
- williamdclt 6y agoYou don't need any "significant" advantage. Even a very small advantage ("an anonymous struct would be handy here") is enough, why would you _not_ use it when it's free? For the fun of the constraint? I'm not a C expert but I don't think there's any downside to using the C11 standard compared to C99
- jlokier 6y agoOne downside is reduced portability. If you're writing in C that's often a motivation. The number of platforms with a C11 compiler is lower than the number of platforms with a C99 compiler.
- userbinator 6y ago...which is lower than the number of platforms with a C89 compiler. A lot of popular projects known for their high portability are C89 for this reason. There's also the fact that there are far more compilers for C89, and it is easier to write one than for the newer standards. This becomes important if you are interested in avoiding Ken Thompson attacks. Personally, I still stick to C89 and the only newer feature that I've found to be useful is mixed declarations and statements, but it's no big loss as it both avoids the "variable proliferation" that some codebases seem to be afflicted with, and blocks can be used to start a new inner scope if you really need a new set of declarations anyway.
- cellularmitosis 6y agoIs there an equivalent of babel.js for C, which would translate C99 into C89?
- chriszhang 6y agoWhat are Ken Thompson attacks? I searched online but did not find anything informative. Can someone explain what these attacks are?
- Macha 6y agoSee "Reflections on Trusting Trust"
- boogies 6y agoWhich search engine? DuckDuckGo had a useful result right at the top https://duckduckgo.com/?q=Ken+Thompson+attacks https://duckduckgo.com/?q=Ken+Thompson+attacks > https://softwareengineering.stackexchange.com/questions/184874/is-ken-thompsons-compiler-hack-still-a-threat https://softwareengineering.stackexchange.com/questions/1848... (although the answer to the linked question https://softwareengineering.stackexchange.com/questions/194746/what-is-the-ken-thompson-hack?noredirect=1&lq=1 https://softwareengineering.stackexchange.com/questions/1947... explained better to me).
- a1369209993 6y agoThey're actually called trusting trust attacks (the original paper on the topic is "Reflections on Trusting Trust" if you want a guarranteed search term); I'm not sure why userbinator used a eponym instead. I'm also not sure why they would be relevant for a general project, since the source language being easy to write a alternate compiler for only matters for the compiler itself: once you have non-infected compiler, you can bootstrap gcc or whatever and compile everything else at whatever C standard you like.
- userbinator 6y agoI'm not sure why userbinator used a eponym instead. It's the first thing that came to mind when I thought of the concept. Perhaps this discussion may yield some additional insight: https://news.ycombinator.com/item?id=24385389 https://news.ycombinator.com/item?id=24385389
- phone8675309 6y agoOlder standards typically have a larger pool of people who can contribute because the standard has been around longer. A programmer might have more experience with an older standard due to the length of time has been out or because the toolchain they use elsewhere (personal projects, embedded comes to mind, or work) hasn't updated to the new standard. Coming up to speed with the new standard is not free. The tooling may be free for the most common targets (embedded usually lags), but taking the time to learn isn't free.
- dependenttypes 6y agoIt certainly is free. The standards are generally backwards compatible and the changes are simple. You do not even need to be aware about the differences between C89 and C11 to contribute to a C11 project. > or because the toolchain they use elsewhere (personal projects, embedded comes to mind, or work) hasn't updated to the new standard. gcc and clang both support it.
- cellularmitosis 6y agoThe latest gcc and clang might not be available on a particular platform.
- superkuh 6y agoWhen you start using new features you break backwards compilability. For C11 that means distros as new as Ubuntu 10.04 (which I still use as my main desktop) and the like are going to have problems compiling (GCC it ships with only supports parts, as in C1X). This will also apply to older embedded systems where a tiny client would be useful. In the past a compiler and ecosystem would last a decade before it couldn't compile something. These days changes are coming out, and being used, every 3 years. It's future shock and the major cause of container usage on the desktop and in academia. Sticking with a well established older standard means everyone can avoid the massive increase in complexity and problems that containers bring.
- KuiN 6y agoOut of interest, why are you using a 10 year old OS that went out of support _7 years ago_? That must have horrible security implications, surely?
- superkuh 6y ago>That must have horrible security implications, surely? Lets just say it's a matter of taste. I keep my attack surfaces to a minimum, backport what I can "patch and statically compiled deps for userspace"-wise. On the otherhand, I browse the web with javascript disabled so my old box probably has less "horrible security implications" than a completely up to date distro with the user blindly executing all code they're sent. Security is behavior more than software.
- beefhash 6y ago> Why use C11 over C99? C11 gives you noreturn and alignas. Alignas can be pretty useful for low-level development in particular. Just hope you don't need variable-length arrays because those got changed to optional. > Or even why use C99 over C89? Several very big things: Native bool, stdint.h (fixed-width int types with known sizes ahead of time), long long, snprintf, not having to declare all variables at the top of the block (and now you can do for (size_t i = 0; i < sizeof(strbuf); ++i) because of it).
- flohofwoe 6y agoC99 over C89: designated initialization and compound literals are the biggies, plus all the small accumulated improvements that had been added to C during the 90's (e.g. variable declaration anywhere, for (int...), winged comments...)
- archi42 6y agoI'm currently porting some "C99"-ish code, and I had a few instances for which I would have loved just use C11's `_Generic` to replace a macro-hell with statement expressions and accompanying `typeof()`s all over the place. Fun fact: `typeof` is a GNU extension, and the target compiler doesn't have that.
- nrclark 6y agoIn addition to other's comments, C11 also gives you: - static_assert, for ensuring things at compile-time without ugly macros. - atomics, for use in multi-threaded systems.
- mmozeiko 6y agoThis source code seems tiny - just ~300 lines. What features of c11 do you think would be useful to use there?
- mcpcpc 6y agogood question! no real reason, other than C99 being the standard that i started development in. With that said, I see no reason not to switch ;)
- zserge 6y agosuckless did something similar: http://tools.suckless.org/sic/ http://tools.suckless.org/sic/
- zserge 6y agoas well as a file-based tiny IRC client in C: http://tools.suckless.org/ii/ http://tools.suckless.org/ii/
- mcpcpc 6y agothe suckless IRC clients are awesome! in fact, `sic` was my “go to” before writing `kirc`. I’m definitely not trying to compete with those, especially their file-based approach (which is great for users that work across channels) but rather offer a lightweight and “clean-looking” solution for the casual user.
- socraticdev 6y agooh! i may be trying this hover the week-end :)
- userbinator 6y agoThe IRC protocol is both text-based and simple enough that you can use something like netcat as a client (and I have, many times.) The line-based format fits IM perfectly, and the overhead of the protocol is a tiny fraction of the bloated proprietary ones that have filled this use-case today (except MSNP, which in its earlier versions was also delightfully simple and easy to write a client for, but definitely beyond the threshold of being usable "raw".)
- sys_64738 6y agoI've used telnet as the client wait in the distant pass. Those were the days.
- Fnoord 6y agoYou could use netcat (or something akin to it). Back in the days I tunneled that via stunnel to get TLS [1] support. One could do the same with POP3 and IMAP. One problem with this workflow is that in some clients (e.g. IRC client supporting TLS) the user had no way to identify/verify the certificate. If a client just automatically accept self-signed certificates, its just snake oil. [1] Everyone still called it SSL back then. Oh, wait...
- sys_64738 6y agoI never did SSL from telnet for sure, in fact I didn't know IRC supported encryption back then. There was also the ident response that was needed - can't recall the particulars as it's been 20+ years.
- Fnoord 6y agoI was talking end of 90s. UnrealIRCd (mainly Carsten Munk / stskeeps) was one of the first to support TLS/SSL. At some point in start of 00s the popular IRC networks slowly but surely started to support it. There's also the case for cryptography between servers, something UnrealIRCd also was quick to adapt. Some servers required ident(d) response which required a server running on privileged port 113.
- tmsbrg 6y agoIRC in 307 rules of C code without dependencies, pretty cool. Of course for that to work they had to sacrifice secure TLS support. Based on the "do one thing well" I was thinking you could set up a TLS tunnel from localhost:6667 to <irc-server>:6697 Not really perfect but my WIP attempt using `socat`: `socat -v tcp-listen:6667,reuseaddr,fork,bind=127.0.0.1 ssl:<irc-server>:6697` then connect to it: `./kirc -s 127.0.0.1 -c 'channel' -n 'name' -r 'realname'` not sure what TLS version socat uses by default, might be something horrible :)
- mcpcpc 6y agooohh interesting. will throw this in as an “example”. thanks!
- anthk 6y agoThanks, this will work for SIC too.
- vaccinator 6y agoAny chance you know how to do encrypted dcc sends too?
- visualphoenix 6y agoFWIW I’ve had great success using ghostunnel[0] instead of stunnel in prod. Big fan. [0] https://github.com/ghostunnel/ghostunnel https://github.com/ghostunnel/ghostunnel
- projektfu 6y agoLooks cool. I wonder whether users can overflow your buffers inputting commands in sscanf. Also, why malloc/free cmd_str in raw? You're automatically or statically allocating all the other buffers.
- mcpcpc 6y agowill fix that. thank you!
- CyberRabbi 6y agoCool project. I would relax the requirements from C99 to C89. You get more portability to cool retro systems that way and C99 doesn’t really add that much. Also C++ compilers are generally more able to compile C89 in C++ mode than C99, e.g. msvc
- mcpcpc 6y agodefinitely a good idea. will add that to the “todo” list
- snvzz 6y agoTo the contrary, I wouldn't. Using C99 + POSIX is the defining fact about your project. I would let somebody else write a C89 irc client, instead.
- flohofwoe 6y agoAgreed, also "retro system compiler" doesn't mean it only supports old C standards, e.g. SDCC is C99 and C11 compatible. IMHO strict C89 is a much less enjoyable language to read and write than C99, for instance designated initialization and compound literals are massive improvements. Also MSVC's C99 support is pretty good since ca. VS2015.
- snvzz 6y agoI was similarly thinking vbcc.
- cogburnd02 6y agocc65 ( https://github.com/cc65/cc65 https://github.com/cc65/cc65 ) doesn't do C99 "and never will" according to https://cc65.github.io/doc/cc65.html https://cc65.github.io/doc/cc65.html but it's probably the most developed C compiler for 6502-based systems.
- snvzz 6y ago
- knorker 6y agoA little sloppy with the error handling, but pretty neat. E.g. log_append() doesn't check fopen return value, malloc() return isn't checked, and a write() can return a partial write, thus needs a loop. fcntl(). Also write() should check for EINTR&EAGAIN. And also there's no handling for nonblocking write. If the user types too much while the network glitches it seems that this could cause the client to exit(). Probably the correct way is to not read from stdin unless poll() returns that writing to the socket is safe, and vice versa. connect() errors should print where they failed to connect. And: $ ./kirc Nick not specified: Success And in my first test I got: Write to socket: Resource temporarily unavailable And I see a lot of NULL pointers being printed when I connect to e.g. freenode. And so on, and so on… For these things I recommend re-reading the manpage for every libc and syscall you call, and check how they can fail, and consider how you can handle that failure. 307 lines of pure C is a pretty neat minimal actually usable client, so I'm not saying it's not well done. But that thing about "… and do it well" (from the readme) means doing all of the above. The problem, of course, is that fixing these problems well is "the other 90% of the work", especially when coding in C. And this is the main reason I avoid C when I can. You can't just call "write()". You have to write a 5-10 line wrapper function, and then all callers need a few lines of error handling. And so it goes for everything, until your program is no longer the nice 300 line neat thing you can almost write from memory. So it's a good start. But it's pretty fragile in its current form.
- mcpcpc 6y agoi appreciate the honest feedback! definitely a work in progress and i have learned a lot since i started ~1mo ago on this. will take your suggestions and add them to my ever growing “todo” list. ;)
- stingraycharles 6y ago> malloc() return isn't checked small digression, but I thought that at least on Linux, malloc() never returns an error because the actual allocation happens lazily, when the memory is first used?
- formerly_proven 6y ago
- tankfeeder 6y ago144 lines IRC client on PicoLisp: https://picolisp.com/wiki/?ircClient https://picolisp.com/wiki/?ircClient
- pjmlp 6y agoAnd most likely CVE free.
- jbirer 6y agoGreat client, I have been using it for about a week. I would suggest to add a channel indicator before the nickname so you can see from what channel the message being sent from but otherwise great work.
- mcpcpc 6y agothanks! i should note that channel indication exists already. it will appear, however, only for channels other than the one connected to initially.
- moonbug 6y ago"Written in C" should be considered a warning
- lokedhs 6y agoI actually feel bad about pointing out issues with this code since the project is very neat. But, I'm still going to do it. There is a problem where the code uses explicit escape sequences for colour instead of using terminfo. This is a pet peeve of mine, because it prevents things like controlling whether or not to use colour by setting TERM to the appropriate values. Or to completely disable highlighting by setting TERM to "dumb". Or even use a completely different terminal type, like if you have an old vt52 hooked up to your computer. Terminfo is a really nice library that abstracts away all the terminal codes. It's really what should be used here.
- mcpcpc 6y agointeresting argument. will look into it
- xellisx 6y agoAny love for mIRC?