summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2018-07-18 23:46:06 +0100
committerTomasz Kramkowski <tk@the-tk.com>2018-07-18 23:55:42 +0100
commitc34ae6fed8503c6f8b27b4bd55cf26bb3f47ad23 (patch)
treea50e1f923f5101846e440fba4b076b14d8ac6b4b
downloadthe-tk.com-c34ae6fed8503c6f8b27b4bd55cf26bb3f47ad23.tar.gz
the-tk.com-c34ae6fed8503c6f8b27b4bd55cf26bb3f47ad23.tar.xz
the-tk.com-c34ae6fed8503c6f8b27b4bd55cf26bb3f47ad23.zip
init commit
-rw-r--r--.gitignore4
-rw-r--r--content/images/EFF.pngbin0 -> 696 bytes
-rw-r--r--content/images/FSF.pngbin0 -> 893 bytes
-rw-r--r--content/images/FSF.svg34
-rw-r--r--content/images/GNU.pngbin0 -> 853 bytes
-rw-r--r--content/images/ccbysa.pngbin0 -> 428 bytes
-rw-r--r--content/images/glider-yellow.pngbin0 -> 225 bytes
-rw-r--r--content/images/grid_noise.pngbin0 -> 4638 bytes
-rw-r--r--content/images/icon16x16.pngbin0 -> 553 bytes
-rw-r--r--content/images/icon32x32.pngbin0 -> 556 bytes
-rw-r--r--content/posts/2015-06-28-it_s-alive-again.md75
-rw-r--r--content/posts/2015-08-16-mystery-ds-record.md79
-rw-r--r--content/posts/2015-12-02-malloc-realloc-and-sizeof.md87
-rw-r--r--content/posts/2016-04-04-dnssec.md25
-rw-r--r--content/posts/2018-07-18-n900-fast-gps-fix.md39
-rw-r--r--content/projects/c-stuff.md22
-rw-r--r--content/projects/dotfiles.md6
-rw-r--r--content/projects/minecurses.md8
-rw-r--r--content/projects/the-tk.com.md45
-rw-r--r--content/projects/vav.md6
-rw-r--r--content/style.scss153
-rwxr-xr-xgenerate.py178
-rw-r--r--meta.py28
-rwxr-xr-xmksite.sh6
-rw-r--r--output/.gitignore2
-rwxr-xr-xserve.sh4
-rw-r--r--templates/blog.html7
-rw-r--r--templates/default.html46
-rw-r--r--templates/error.html5
-rw-r--r--templates/index.html22
-rw-r--r--templates/post.html16
-rw-r--r--templates/project.html16
-rw-r--r--templates/projects.html11
-rw-r--r--templates/tag.html7
34 files changed, 931 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..593c152
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.pyc
+*.tgz
+.sass-cache
+__pycache__
diff --git a/content/images/EFF.png b/content/images/EFF.png
new file mode 100644
index 0000000..9701d8e
--- /dev/null
+++ b/content/images/EFF.png
Binary files differ
diff --git a/content/images/FSF.png b/content/images/FSF.png
new file mode 100644
index 0000000..c7cb606
--- /dev/null
+++ b/content/images/FSF.png
Binary files differ
diff --git a/content/images/FSF.svg b/content/images/FSF.svg
new file mode 100644
index 0000000..e3f8d47
--- /dev/null
+++ b/content/images/FSF.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="1115.9464"
+ height="490.18243"
+ id="svg2434">
+ <defs
+ id="defs2436" />
+ <g
+ transform="translate(232.25893,-284.41382)"
+ id="layer1">
+ <g
+ transform="matrix(1.24994,0,0,1.24994,-232.25893,280.59622)"
+ id="g5"
+ style="fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4">
+ <clipPath
+ id="aiclp1">
+ <path
+ d="M 0,0 L 3390.47,0 L 3390.47,395.159 L 0,395.159 L 0,0 z"
+ id="path8" />
+ </clipPath>
+ <g
+ id="g10">
+ <path
+ d="M 86.4,193.619 L 0,193.619 L 0,128.819 L 86.4,128.819 L 86.4,78.419 L 72,78.419 L 72,42.419 L 86.4,42.419 L 86.4,28.019 L 122.4,28.019 L 122.4,42.419 L 338.4,42.419 C 398.068,11.152 468.102,5.081 528.635,4.336 C 595.448,3.478 598.91,4.229 626.165,4.424 C 741.533,5.283 749.485,5.792 765.768,3.223 C 772.332,2.142 779.531,6.483 780.1,9.718 C 781.423,16.89 766.474,25.196 761.858,26.659 C 747.507,31.214 721.815,33.275 651.929,37.307 L 650.265,37.341 C 539.276,47.821 477.012,73.988 460.922,81.476 C 397.281,111.179 390.411,125.007 398.685,133.831 C 407.453,143.189 456.997,122.605 481.292,115.667 C 529.574,101.893 558.027,115.084 576,128.819 L 619.2,128.819 L 619.2,121.619 L 648,121.619 L 648,128.819 L 892.8,128.819 L 892.8,193.619 L 648,193.619 L 648,244.02 L 856.8,244.02 L 856.8,280.02 L 648,280.02 L 648,395.219 L 619.2,395.219 L 619.2,280.02 L 604.8,280.02 L 604.8,244.02 L 619.2,244.02 L 619.2,193.619 L 604.8,193.619 C 604.551,219.088 597.091,242.438 589.952,252.057 C 523.32,341.562 221.084,353.077 127.459,354.605 C 103.834,355.01 86.923,351.047 86.4,344.818 M 253.773,127.251 C 257.812,110.263 269.098,92.953 282.619,78.547 L 124.419,79.178 L 123.845,129.016 L 252.962,129.54 L 253.572,130.573 M 751.955,11.815 C 750.31,10.996 666.288,15.679 661.564,15.25 C 656.841,14.82 606.225,15.545 578.474,14.82 C 545.624,13.961 511.15,14.854 479.065,17.826 C 446.645,20.832 413.151,30.923 385.455,42.517 C 359.107,53.548 332.851,67.422 312.24,83.74 C 301.685,92.094 293.661,101.373 286.476,112.726 C 278.317,125.607 274.384,140.322 279.819,152.661 C 285.678,165.945 298.781,171.829 315.031,174.346 C 329.785,176.64 347.881,175.419 359.475,177.781 C 366.359,179.183 377.658,181.035 378.369,187.658 C 379.013,193.669 368.163,203.721 363.125,206.121 C 353.678,210.631 341.01,206.766 328.772,204.189 C 320.337,202.418 307.819,198.311 300.001,194.741 C 294.722,192.327 289.074,190.421 288,190.421 C 287.572,190.421 122.187,189.993 122.4,190.421 C 122.4,193.212 122.187,327.981 122.4,334.421 C 122.635,341.533 147.178,339.426 162.376,337.95 C 191.737,335.077 222.278,331.508 251.908,327.215 C 268.85,324.759 286.805,321.578 303.866,318.196 C 330.919,312.83 363.267,305.314 376.718,301.019 C 410.36,290.285 445.142,280.838 476.918,267.097 C 491.204,260.924 508.265,253.141 519.86,245.196 C 532.218,236.728 545.409,225.014 550.992,212.991 C 557.191,199.639 559.089,183.563 552.709,168.976 C 546.698,155.235 530.165,142.998 515.78,140.635 C 507.593,139.293 501.18,138.488 493.236,139.132 C 484.098,139.87 468.545,143.211 458.239,144.5 C 441.297,146.62 421.39,149.633 404.777,147.077 C 393.613,145.358 376.007,130.974 382.233,114.227 C 386.796,101.948 404.475,89.347 415.083,82.451 C 440.848,65.703 487.197,51.083 526.945,41.656 C 560.438,33.713 607.458,27.271 647.179,26.842 C 651.009,26.802 686.892,24.393 690.549,24.265 C 750.881,22.118 752.813,12.242 751.955,11.813"
+ id="path12"
+ style="fill:#b11107;stroke:none" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/content/images/GNU.png b/content/images/GNU.png
new file mode 100644
index 0000000..5382e18
--- /dev/null
+++ b/content/images/GNU.png
Binary files differ
diff --git a/content/images/ccbysa.png b/content/images/ccbysa.png
new file mode 100644
index 0000000..9c0b590
--- /dev/null
+++ b/content/images/ccbysa.png
Binary files differ
diff --git a/content/images/glider-yellow.png b/content/images/glider-yellow.png
new file mode 100644
index 0000000..4edeca1
--- /dev/null
+++ b/content/images/glider-yellow.png
Binary files differ
diff --git a/content/images/grid_noise.png b/content/images/grid_noise.png
new file mode 100644
index 0000000..30d1be4
--- /dev/null
+++ b/content/images/grid_noise.png
Binary files differ
diff --git a/content/images/icon16x16.png b/content/images/icon16x16.png
new file mode 100644
index 0000000..2c77bc3
--- /dev/null
+++ b/content/images/icon16x16.png
Binary files differ
diff --git a/content/images/icon32x32.png b/content/images/icon32x32.png
new file mode 100644
index 0000000..7ffd840
--- /dev/null
+++ b/content/images/icon32x32.png
Binary files differ
diff --git a/content/posts/2015-06-28-it_s-alive-again.md b/content/posts/2015-06-28-it_s-alive-again.md
new file mode 100644
index 0000000..ccc34a4
--- /dev/null
+++ b/content/posts/2015-06-28-it_s-alive-again.md
@@ -0,0 +1,75 @@
+$title "It's alive... again..."
+$tags webdev
+
+After putting it off for a few months, and a weekend of trying to make the
+perfect simple stylesheet, I finally got around to re-doing my website. It's
+now simpler, easier to read and actually has a blog.
+
+$pre
+
+Initially I was going to write my own static content generator in python using
+[Jinja2][jinja], pygments and docutils. I realise that doing this was going to
+be a giant pain and I didn't quite have the time to actually try to make one.
+I've heard about [Jekyll][jekyll] before and decided to investigate. I was
+hoping it was written in python but was instead written in ruby, however, in
+the end, this didn't matter.
+
+I was initially greeted by an _interesting_ layout and became worried that if I
+went any further I would be here for the rest of the day trying to wrangle the
+thing into submission.
+
+I started with the basics, I changed a few details in the config, this made
+some text change and remove some other text so I went about exploring. I knew
+Jekyll was using [Liquid][liquid] templates and having used Jinja before I knew what I
+was looking for.
+
+I quickly discovered that `/_layouts` stored a set of "base" templates which
+included a set of templates from `/_includes` to bring stuff together. This
+wasn't too bad.
+
+I then found `/css` or more importantly `/css/main.scss`. I've never seen an
+"scss" extension before but at first glance it looked a bit like CSS. At a
+second glance it looked like a css generator. I didn't really need this, the
+CSS for this website is in no way complex enough to warrant templating css, so
+I got to work modifying the existing `_layouts` and `_includes`, and simply
+copied in my usual css.
+
+Within about 10 minutes I had a working front page design but I noticed
+something annoying; the generated HTML had about 10 line breaks in the middle
+and generally looked like a mess. I realised that most of this space was
+because of Liquid's tokens leaving space. After moving all the tokens around in
+a way which meant that minimal breaks were introduced, I was left with
+something presentable.
+
+But this wasn't the end of the weirdness, the next problem was that for some
+reason, the indentation on the very first line of an imported template was
+always correct, but subsequent indentation was broken. (I was hoping that, like
+many text editors, Liquid might take the indent on the line where a block is
+being pasted and copy it for every line of the block, but on second thought,
+this might not be desirable for for example, `<pre>`). I had to fix this by
+indenting all but the first line correctly in every `/_includes` template and
+this managed to cover most of the cases.
+
+In the end, after pasting the syntax highlighting from
+`/_sass/_syntax-highlighting.scss` into my stylesheet and manually "generating"
+all the required entries. I was left with this very end result you see before
+you. As a final verdict, I really do think that Jekyll is quite awesome even
+though I've probably not used it in the most efficient fashion. All things
+considered, however, this only took about an hour.
+
+Now, bask in the glory of the syntax highlighting:
+
+~~~.c
+#include <stdio.h>
+
+int main(void)
+{
+ puts("Colours!!!");
+
+ return 0;
+}
+~~~
+
+[jekyll]: http://jekyllrb.com
+[jinja]: http://jinja.pocoo.org/
+[liquid]: http://liquidmarkup.org/
diff --git a/content/posts/2015-08-16-mystery-ds-record.md b/content/posts/2015-08-16-mystery-ds-record.md
new file mode 100644
index 0000000..9757503
--- /dev/null
+++ b/content/posts/2015-08-16-mystery-ds-record.md
@@ -0,0 +1,79 @@
+$title "The mystery DS record"
+$tags DNS DNSSEC
+
+So after transferring my domain from transip.eu to namecheap.com for WHOIS
+privacy I realised that suddenly the Google public DNS servers were no longer
+able to resolve my domain. Very quickly, I realised that quite a few things
+seemed to rely on the Google public DNS services (and DNSSEC supporting
+resolvers). Fun ensued.
+
+$pre
+
+DNSSEC is a fancy extension to DNS which allows resolvers to cryptographically
+confirm, through the use of some public keys and signatures, that the records
+they are looking up are in fact the records they want and not the result of
+some MITM attack. This is explained well in multiple places, so I won't explain
+it here.
+
+I transferred my domain from transip.eu who provide DNSSEC (no way to publish
+DS records, everything is maintained in the background), but don't provide
+WHOIS privacy, to namecheap.com who do provide WHOIS privacy but don't provide
+DNSSEC. The DS record that transip.eu published to gtld-servers for their
+DNSSEC was left published after I transferred which initially, for someone who
+didn't know anything about DNSSEC, caused many confusing side effects.
+
+DS records have to be published in the parent zone, this means that it has to
+be done through your registrar. (Unless you have a lot of money and time and
+feel like bribing Verisign. If someone knows how to do this without bribery,
+tell me!). Upon contacting namecheap about the issue, the person I was talking
+to seemed confused about the issue. They seemed to think I was having issues
+with A and AAAA records and DNS propagation. They tried to inform me that I
+just had to wait. Of course, all the waiting in the world wouldn't get the DS
+records to disappear so after explaining the situation a bit better (I still
+didn't quite know much about it myself) I got them to contact their "upstream
+DNS provider."
+
+Finally, a weekend later, the DS record was gone and Google's DNS servers were
+serving my records again. Additionally, I switched over to using my own BIND
+name server so I could have full control over my DNS. This proved to be quite
+fun to set up. The second server is hosted by a good friend of mine and the
+third one by a friend of that friend. So far, other than me accidentally
+forgetting to enable named.service and rebooting my server to find that DNS
+wasn't working very well, I've had no problems.
+So after transferring my domain from transip.eu to namecheap.com for WHOIS
+privacy I realised that suddenly the Google public DNS servers were no longer
+able to resolve my domain. Very quickly, I realised that quite a few things
+seemed to rely on the Google public DNS services (and DNSSEC supporting
+resolvers). Fun ensued.
+
+DNSSEC is a fancy extension to DNS which allows resolvers to cryptographically
+confirm, through the use of some public keys and signatures, that the records
+they are looking up are in fact the records they want and not the result of
+some MITM attack. This is explained well in multiple places, so I won't explain
+it here.
+
+I transferred my domain from transip.eu who provide DNSSEC (no way to publish
+DS records, everything is maintained in the background), but don't provide
+WHOIS privacy, to namecheap.com who do provide WHOIS privacy but don't provide
+DNSSEC. The DS record that transip.eu published to gtld-servers for their
+DNSSEC was left published after I transferred which initially, for someone who
+didn't know anything about DNSSEC, caused many confusing side effects.
+
+DS records have to be published in the parent zone, this means that it has to
+be done through your registrar. (Unless you have a lot of money and time and
+feel like bribing Verisign. If someone knows how to do this without bribery,
+tell me!). Upon contacting namecheap about the issue, the person I was talking
+to seemed confused about the issue. They seemed to think I was having issues
+with A and AAAA records and DNS propagation. They tried to inform me that I
+just had to wait. Of course, all the waiting in the world wouldn't get the DS
+records to disappear so after explaining the situation a bit better (I still
+didn't quite know much about it myself) I got them to contact their "upstream
+DNS provider."
+
+Finally, a weekend later, the DS record was gone and Google's DNS servers were
+serving my records again. Additionally, I switched over to using my own BIND
+name server so I could have full control over my DNS. This proved to be quite
+fun to set up. The second server is hosted by a good friend of mine and the
+third one by a friend of that friend. So far, other than me accidentally
+forgetting to enable named.service and rebooting my server to find that DNS
+wasn't working very well, I've had no problems.
diff --git a/content/posts/2015-12-02-malloc-realloc-and-sizeof.md b/content/posts/2015-12-02-malloc-realloc-and-sizeof.md
new file mode 100644
index 0000000..ee3f508
--- /dev/null
+++ b/content/posts/2015-12-02-malloc-realloc-and-sizeof.md
@@ -0,0 +1,87 @@
+$title "malloc, realloc and sizeof"
+$tags information C
+
+I spend a lot of time in ##c hoping to provide useful information to people
+wishing to learn and understand C and almost every day I see malloc and realloc
+code which appears to be straight from a horror movie. I've had to say what I
+say in this post repeatedly to many people so I've decided that it's time to
+write it once and simply give people a link every time I wish to explain why
+such code is incorrect.
+
+$pre
+
+The code I'm describing is usually a combination of some or all of this:
+
+~~~ c
+struct foo *bar;
+
+bar = (struct foo *)malloc(sizeof(struct foo) * 10);
+
+bar = (struct foo *)realloc(bar, sizeof(struct foo) * 20);
+~~~
+
+There are multiple issues with this:
+
+ - Casting malloc can hide newbie mistakes such as forgetting to include
+ stdlib.h which can in turn cause strange issues down the line.
+ - Casting unnecessarily also gives you rather long lines, especially when you
+ have a rather complicated/long type (e.g. const struct foo * const *).
+ - You're having to type the same thing three times, when you could type it
+ once.
+ - If you screw up rewriting the same thing one of three times, you might end
+ up allocating the wrong amount of space and still end up with code which
+ runs, this can be dangerous down the line if some clever person finds a way
+ to exploit this.
+ - If you ever want to change the type of bar, you need to change it in 3
+ places, if you forget to change it in one of these, you end up with the same
+ issue described in the point above.
+ - Finally (regarding just the realloc line) if realloc fails, memory is leaked
+ since bar's original value is overwritten with NULL, realloc doesn't
+ automatically free the original pointer when it can't realloc.
+
+The easy solution is simply:
+
+~~~ c
+struct foo *bar, *tmpbar;
+
+bar = malloc(sizeof *bar * 10);
+
+tmpbar = realloc(bar, sizeof *tmpbar * 20);
+
+if (!tmpbar) {
+ free(bar);
+ /* error handling */
+} else {
+ bar = tmpbar;
+}
+~~~
+
+This solves all of the outlined problems.
+
+-----------------------
+
+Here's the answers to two common questions:
+
+**Q**: _The compiler has always complained (warned) when I tried to assign a
+pointer to one type to a pointer to another type. Would this not be the case
+here?_
+
+**A**: The C standard states (C11/C99 §6.3.2.3 and C11/C99 §6.5.16.1) roughly
+that a pointer to void can be assigned to a pointer to any type, and vice
+versa, freely without issuing a warning. This in turn means that the return
+value of malloc (and any other function returning void \*) will be converted
+without warning to the desired type without needing a cast.
+
+**Q**: _What's the deal with `sizeof *bar`? Don't functions need
+brackets?_
+
+
+**A**: The sizeof operator can be given an expression as an operand as well as
+the parenthesized name of a type. This means we can do `sizeof *bar`. Also,
+since sizeof is an _operator_ and **not** a function, it doesn't require
+parentheses when its operand is an expression, the C standard does however
+require that for types, the type name has to be parenthesized. In the end, it's
+a style choice whether the parentheses are always there or not, but personally I
+think leaving them out is more consistent. (NB: The first example uses sizeof as
+such: `sizeof(type)`, personally I prefer leaving a space between `sizeof` and
+`(type)` as I would with most other operators.)
diff --git a/content/posts/2016-04-04-dnssec.md b/content/posts/2016-04-04-dnssec.md
new file mode 100644
index 0000000..13c1d60
--- /dev/null
+++ b/content/posts/2016-04-04-dnssec.md
@@ -0,0 +1,25 @@
+$title "DNSSEC"
+$tags information DNS DNSSEC
+
+As of today my domain finally supports DNSSEC. It was much simpler than I
+thought it would be. It seems namecheap now officially allows you to publish DS
+records in the parent zone of your domain (limited only to TLDs which support
+it). This is one of the last things that I wanted to set up on my server.
+
+$pre
+
+In the end, the process was made very simple by the existence of
+[this][cheatsheet] which details exactly how to set up DNSSEC on BIND 9.10 or
+higher.
+
+Currently the KSK is SHARSA256 1024 bits and the ZSK is SHARSA256 2048 bits, I
+am considering moving to using a 2048 bit KSK but I'm not sure if there will be
+much of a benefit. I am using NSEC3 with a SHA-1 hash with the opt-out bit
+unset and 100 iterations.
+
+In any case, you can now rest assured that if your resolver uses DNSSEC
+(Google's resolvers will return a failure in case they find a DS record but the
+DNSSEC validation fails) you will be receiving signed and verifiable data. Of
+course, I doubt many people care.
+
+[cheatsheet]: https://kb.isc.org/getAttach/122/AA-01311/DNSSEC-QR-B4.pdf
diff --git a/content/posts/2018-07-18-n900-fast-gps-fix.md b/content/posts/2018-07-18-n900-fast-gps-fix.md
new file mode 100644
index 0000000..33d3482
--- /dev/null
+++ b/content/posts/2018-07-18-n900-fast-gps-fix.md
@@ -0,0 +1,39 @@
+$title "N900 Fast GPS Fix"
+$tags N900 GPS
+
+If anyone is, like me, still using the N900, they may have noticed that
+acquiring an initial GPS fix can take minutes. The reason for this is that even
+in the latest CSSU, supl.nokia.com no longer works as a location server. The fix
+for this is actually relatively quick and easy and will make an initial GPS fix
+take seconds rather than minutes.
+
+$pre
+
+The exact details of what needs to be done can be found in the last few posts of
+[this][tmo-thread] Maemo forum thread. The problem is that supl.nokia.com no
+longer resolves to an IP address. However, this doesn't mean that the server
+behind supl.nokia.com is no longer running. Surprisingly, it still is.
+
+The long and short of it is this:
+
+1. Make sure you have the latest CSSU and a working N900 to begin with;
+2. Go [here][certman] and download `libmaemosec-certman0_0.2.10_armel.deb`,
+ `libmaemosec0_0.2.10_armel.deb`, `maemosec-certman-common-ca_0.2.10_all.deb`,
+ and `maemosec-certman-tools_0.2.10_armel.deb`;
+3. Install the above packages via the command line as root (you'll need gainroot)
+ by using `dpkg -i` (put all the files in their own directory and use `dpkg -i
+ *` to save time);
+4. Edit `/etc/hosts` and change `supl.nokia.com` to point to `52.200.182.188`;
+5. Check it all works by running `cmcli -T common-ca -v supl.nokia.com:7275` and
+ `cmcli -T location-proxy -v supl.nokia.com:7275`, both should say "Verified
+ OK.";
+6. If this doesn't work, try `stop location-proxy` and then
+ `start location-proxy` (as root) and go back to step 5.
+
+GPS fixes should happen very quickly now. If it's the year 2023 and this didn't
+work then good luck finding a new fix, hopefully you put the details on your
+blog too. Alternatively, feel free to contact me and I might still be using the
+N900 and might know how to help.
+
+[tmo-thread]: https://talk.maemo.org/showthread.php?t=90651
+[certman]: http://maemo.merlin1991.at/cssu/community-devel/pool/free/m/maemo-security-certman
diff --git a/content/projects/c-stuff.md b/content/projects/c-stuff.md
new file mode 100644
index 0000000..b310844
--- /dev/null
+++ b/content/projects/c-stuff.md
@@ -0,0 +1,22 @@
+$name c-stuff
+$source https://github.com/EliteTK/c-stuff
+
+c-stuff is a large collection of small projects and snippets of
+code. Numerous people have shown interest in these various snippets so
+although this is not a project itself, it gets a notable mention. Most
+of the code is licensed under the GNU GPLv3.
+
+$desc
+
+## Notable Mentions
+
+### timer
+
+timer is a simple command line beeping countdown timer. It has a very
+simple interface: `timer n{s,m,h,D,M,Y}...` Despite this simplicity,
+it's an incredibly useful tool, the source for it can be found
+[here][timer-src] and there is even an AUR package which can be found
+[here][timer-aur].
+
+[timer-src]: https://github.com/EliteTK/c-stuff/blob/master/timer.c "c-stuff/timer at master · EliteTK/c-stuff"
+[timer-aur]: https://aur.archlinux.org/packages/timer-git/ "timer-git"
diff --git a/content/projects/dotfiles.md b/content/projects/dotfiles.md
new file mode 100644
index 0000000..8c239e3
--- /dev/null
+++ b/content/projects/dotfiles.md
@@ -0,0 +1,6 @@
+$name dotfiles
+$source http://github.com/EliteTK/dotfiles/
+
+These are the files from my .config directory, the only things which are
+actually useful may be the vimrc, i3 config and i3blocks config. These are
+severely out of date.
diff --git a/content/projects/minecurses.md b/content/projects/minecurses.md
new file mode 100644
index 0000000..855ed59
--- /dev/null
+++ b/content/projects/minecurses.md
@@ -0,0 +1,8 @@
+$name minecurses
+$source https://github.com/EliteTK/minecurses/
+$aur minecurses-git
+
+minecurses is a clone of minesweeper written in C using ncurses. The
+code is quite awful in the current master branch and the redo branch is
+not in any way able to be compiled. However, in the future this might
+possibly improve.
diff --git a/content/projects/the-tk.com.md b/content/projects/the-tk.com.md
new file mode 100644
index 0000000..dc87f43
--- /dev/null
+++ b/content/projects/the-tk.com.md
@@ -0,0 +1,45 @@
+$name the-tk.com
+$source https://the-tk.com/cgit/the-tk.com/
+
+This website is an ongoing project of mine, an attempt at writing a simple to
+maintain static website with html which tries to avoid putting <div>s
+everywhere. I also hope that at least some of the stuff I write about can be
+useful to some people.
+
+$desc
+
+## Older Versions
+
+The website is actually on its 4th revision. The files for the 1st revision may
+be lost somewhere (probably for the best) but can find the source for v2 and v3
+of the website in the GitHub repository located [here][old-gh], the "old" branch
+holds v2. v3 of the website relies on a slightly customized liquid, the nature
+of this customization can be found [here][liquid-patch].
+
+## IP Echo Server
+
+An IP echo server is hosted at http://ip.the-tk.com/. Before I was informed that
+you could implement this functionality entirely within nginx (using
+`return 200 $remote_addr`) I had written this short simple fastcgi IP echo
+program in C:
+
+~~~.c
+#include <fcgi_stdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(void)
+{
+ while (FCGI_Accept() >= 0) {
+ puts("Content-type: text/plain; charset=UTF-8");
+ puts("Status: 200 OK");
+ puts("");
+ printf("%s", getenv("REMOTE_ADDR"));
+ }
+
+ return EXIT_SUCCESS;
+}
+~~~
+
+[old-gh]: https://github.com/EliteTK/the-tk.com/ "EliteTK/the-tk.com · GitHub"
+[liquid-patch]: https://github.com/EliteTK/liquid/tree/replace_newlines "EliteTK/liquid at replace_newlines"
diff --git a/content/projects/vav.md b/content/projects/vav.md
new file mode 100644
index 0000000..786c6cd
--- /dev/null
+++ b/content/projects/vav.md
@@ -0,0 +1,6 @@
+$name VAV
+$source https://github.com/EliteTK/vav/
+
+VAV is a C library which aims to provide neat looking vectors in C. These might
+not be entirely practical since they cause quite an overhead in the creation and
+calculations using vectors, but the code can be a source of interesting ideas.
diff --git a/content/style.scss b/content/style.scss
new file mode 100644
index 0000000..e1873b8
--- /dev/null
+++ b/content/style.scss
@@ -0,0 +1,153 @@
+html {
+ background-image: url(./images/grid_noise.png);
+ background-repeat: repeat;
+ background-color: #F3F5F7;
+ font-family: sans-serif;
+ text-align: justify;
+}
+
+main {
+ max-width: 100%;
+ min-width: 60%;
+ width: 50em;
+ margin: 1em auto;
+ padding: 1em;
+ background-color: white;
+ box-shadow: 0 0 5px #888;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#copyright {
+ color: grey;
+ font-size: x-small;
+ text-align: center;
+}
+
+nav {
+ overflow: hidden; width: 100%; font-weight: bold; font-size: large;
+ a { text-decoration: none; }
+ a:link { color: black; }
+ a:visited { color: black; }
+ a:hover { color: grey; }
+ a:active { color: darkgrey; }
+}
+
+code, div.codehilite pre {
+ border: 1px dashed #DDD;
+ background-color: #FAFAFA;
+ padding: 0.1em;
+}
+div.codehilite pre { display: block; overflow: auto; }
+
+.fleft { float: left; }
+.fright { float: right; }
+
+figure {
+ margin: 0 0.5em;
+ figcaption {
+ font-size: small;
+ color: #BBB;
+ text-align: right;
+ border-top: thin dotted grey;
+ }
+}
+
+blockquote { font-family: serif; }
+
+img.icon { height: 0.8em; }
+
+a:link { color: grey; } a:hover { color: lightgrey; }
+a:visited { color: darkgrey; } a:active { color: darkgrey; }
+
+footer { text-align: center; }
+
+hr { border: none; border-top: 1px dashed lightgrey; height: 0px; }
+
+article footer {
+ text-align: right;
+}
+
+time {
+ color: #BBB;
+}
+
+ul.taglist {
+ padding-left: 0;
+ list-style: none;
+ li { display: inline; }
+}
+
+ul.postlist {
+ padding-left: 0;
+ list-style: none;
+}
+
+ul.projects {
+ padding-left: 0;
+ list-style: none;
+}
+
+/* Syntax highlighting mess */
+.codehilite {
+ .c { color: #998; font-style: italic }
+ .err { color: #a61717; background-color: #e3d2d2 }
+ .k { font-weight: bold }
+ .o { font-weight: bold }
+ .cm { color: #998; font-style: italic }
+ .cp { color: #999; font-weight: bold }
+ .c1 { color: #998; font-style: italic }
+ .cs { color: #999; font-weight: bold; font-style: italic }
+ .gd { color: #000; background-color: #fdd }
+ .gd .x { color: #000; background-color: #faa }
+ .ge { font-style: italic }
+ .gr { color: #a00 }
+ .gh { color: #999 }
+ .gi { color: #000; background-color: #dfd }
+ .gi .x { color: #000; background-color: #afa }
+ .go { color: #888 }
+ .gp { color: #555 }
+ .gs { font-weight: bold }
+ .gu { color: #aaa }
+ .gt { color: #a00 }
+ .kc { font-weight: bold }
+ .kd { font-weight: bold }
+ .kp { font-weight: bold }
+ .kr { font-weight: bold }
+ .kt { color: #458; font-weight: bold }
+ .m { color: #099 }
+ .s { color: #d14 }
+ .na { color: #008080 }
+ .nb { color: #0086B3 }
+ .nc { color: #458; font-weight: bold }
+ .no { color: #008080 }
+ .ni { color: #800080 }
+ .ne { color: #900; font-weight: bold }
+ .nf { color: #900; font-weight: bold }
+ .nn { color: #555 }
+ .nt { color: #000080 }
+ .nv { color: #008080 }
+ .ow { font-weight: bold }
+ .w { color: #bbb }
+ .mf { color: #099 }
+ .mh { color: #099 }
+ .mi { color: #099 }
+ .mo { color: #099 }
+ .sb { color: #d14 }
+ .sc { color: #d14 }
+ .sd { color: #d14 }
+ .s2 { color: #d14 }
+ .se { color: #d14 }
+ .sh { color: #d14 }
+ .si { color: #d14 }
+ .sx { color: #d14 }
+ .sr { color: #009926 }
+ .s1 { color: #d14 }
+ .ss { color: #990073 }
+ .bp { color: #999 }
+ .vc { color: #008080 }
+ .vg { color: #008080 }
+ .vi { color: #008080 }
+ .il { color: #099 }
+}
diff --git a/generate.py b/generate.py
new file mode 100755
index 0000000..3c7f1f3
--- /dev/null
+++ b/generate.py
@@ -0,0 +1,178 @@
+#!/usr/bin/env python3
+
+from collections import namedtuple, Counter
+from datetime import date
+from functools import partial
+from glob import glob
+from itertools import chain
+from jinja2 import Environment, FileSystemLoader, Markup
+from markdown import markdown
+from operator import attrgetter
+from subprocess import call as run
+from sys import argv
+import meta
+import os
+
+CONTENT = './content'
+OUTPUT = './output'
+KWORDS = { 'Tomasz Kramkowski', 'the-tk', 'blog', 'projects', 'TK', 'Arch-TK' }
+ERRORS = {
+ 403: "Forbidden",
+ 404: "File Not Found",
+ 500: "Internal Server Error",
+ 502: "Bad Gateway",
+ 503: "Service Unavailable",
+ 504: "Gateway Timeout",
+}
+
+md = lambda s: Markup(markdown(s, extensions=['markdown.extensions.fenced_code',
+ 'markdown.extensions.codehilite']))
+
+File = namedtuple('File', 'content date slug ext')
+def parse(path, has_date=False):
+ with open(path) as f:
+ content = meta.parse(f.read())
+ slug, ext = os.path.splitext(os.path.split(path)[1])
+ if has_date:
+ y, m, d, slug = slug.split('-', 3)
+ dat = date(int(y), int(m), int(d))
+ else:
+ dat = None
+ return File(content, dat, slug, ext)
+
+Post = namedtuple('Post', 'title date tags pre content location')
+def readpost(path):
+ pf = parse(path, has_date=True)
+ location = os.path.join('post',
+ '{:04}'.format(pf.date.year),
+ '{:02}'.format(pf.date.month),
+ '{:02}'.format(pf.date.day),
+ pf.slug + '.html')
+ tags = set(pf.content.meta.get('tags', []))
+ return Post(' '.join(pf.content.meta['title']), pf.date, tags,
+ pf.content.sects['pre'],
+ '\n'.join(pf.content.sects.values()), location)
+
+Project = namedtuple('Project', 'name description source ml aur content location')
+def readproject(path):
+ pf = parse(path)
+ source = pf.content.meta.get('source', [None])[0]
+ ml = pf.content.meta.get('ml', [None])[0]
+ aur = pf.content.meta.get('aur', [None])[0]
+ content = '\n'.join(pf.content.sects.values())
+ location = os.path.join('project', pf.slug + '.html')
+ return Project(' '.join(pf.content.meta['name']),
+ pf.content.sects.get('desc', content), source, ml, aur, content,
+ location);
+
+def output(dest, cont):
+ dest = os.path.join(OUTPUT, dest)
+ destdir = os.path.dirname(dest)
+ if not os.path.exists(destdir):
+ os.makedirs(destdir)
+ with open(dest, 'w') as f:
+ f.write(cont)
+
+def outputpost(env, post, tags):
+ page = {
+ 'title': post.title,
+ 'description': md(post.pre),
+ 'keywords': ', '.join(KWORDS | post.tags),
+ 'date': post.date,
+ 'content': md(post.content),
+ 'tags': sorted(post.tags & set(tags)),
+ }
+ output(post.location, env.get_template('post.html').render(page=page))
+
+def outputtag(env, posts, tag):
+ page = {
+ 'title': 'Posts tagged - {}'.format(tag),
+ 'description': "List of posts tagged '{}'.".format(tag),
+ 'keywords': ', '.join(KWORDS | {tag}),
+ 'tag': tag,
+ 'posts': [ p for p in posts if tag in p.tags ],
+ }
+ output('tag/{}.html'.format(tag), env.get_template('tag.html').render(page=page))
+
+def outputproject(env, project):
+ page = {
+ 'title': project.name,
+ 'description': project.description.replace('\n', ' '),
+ 'keywords': ', '.join(KWORDS | {project.name}),
+ 'content': md(project.content),
+ 'source': project.source,
+ 'ml': project.ml,
+ 'aur': project.aur,
+ }
+ output(project.location, env.get_template('project.html').render(page=page))
+
+def main(argv=['generate.py']):
+ from getopt import getopt
+ global OUTPUT
+
+ opts = dict(getopt(argv[1:], "o:b:")[0])
+ OUTPUT = opts.get('-o', OUTPUT)
+ baseurl = opts.get('-b', 'https://the-tk.com')
+
+ run(['rm', '-rf', os.path.join(OUTPUT, '*')])
+
+ env = Environment(loader=FileSystemLoader('./templates'), autoescape=True)
+ env.globals['site'] = {'baseurl': baseurl}
+ env.filters['datefmt'] = lambda d, f='%Y-%m-%d': d.strftime(f)
+
+ posts = glob(os.path.join(CONTENT, 'posts', '*'))
+ posts = [p for p in posts if not os.path.split(p)[1].startswith('_')]
+ posts = sorted(map(readpost, posts), key=attrgetter('date'), reverse=True)
+ tags = Counter(chain(*(p.tags for p in posts)))
+ tags = sorted(k for k, v in tags.items() if v > 1)
+
+ page = {
+ 'title': 'Blog',
+ 'description': 'New posts will appear chronologically on this page.',
+ 'keywords': ', '.join(KWORDS),
+ 'tags': tags,
+ 'posts': posts,
+ }
+ output('blog.html', env.get_template('blog.html').render(page=page))
+
+ projects = glob(os.path.join(CONTENT, 'projects', '*'))
+ projects = [p for p in projects if not os.path.split(p)[1].startswith('_')]
+ projects = sorted(map(readproject, projects), key=lambda e: e.name.lower())
+
+ page = {
+ 'title': 'Projects',
+ 'description': 'This is a listing of all of my notable projects.',
+ 'keywords': ', '.join(KWORDS),
+ 'projects': projects,
+ }
+ output('projects.html', env.get_template('projects.html').render(page=page))
+
+ page = {
+ 'title': 'the-tk.com',
+ 'description': 'This is my website. Here you can find some blog posts and descriptions for notable projects.',
+ 'keywords': ', '.join(KWORDS),
+ 'posts': posts[:3],
+ }
+ output('index.html', env.get_template('index.html').render(page=page))
+
+ for post in posts:
+ outputpost(env, post, tags)
+ for tag in tags:
+ outputtag(env, posts, tag)
+ for project in projects:
+ outputproject(env, project)
+
+ for code, error in ERRORS.items():
+ page = {
+ 'title': 'Error: {} - {}'.format(code, error),
+ 'code': code,
+ 'error': error,
+ }
+ output('error/{}.html'.format(code), env.get_template('error.html').render(page=page))
+
+ run(['scss', os.path.join(CONTENT, 'style.scss'), os.path.join(OUTPUT, 'style.css')])
+ run(['cp', '-r', os.path.join(CONTENT, 'images'), OUTPUT])
+
+if __name__ == '__main__':
+ from sys import argv
+ main(argv)
diff --git a/meta.py b/meta.py
new file mode 100644
index 0000000..7bb948d
--- /dev/null
+++ b/meta.py
@@ -0,0 +1,28 @@
+from collections import OrderedDict, deque, namedtuple
+import shlex
+
+Meta = namedtuple('Meta', ['sects', 'meta'])
+
+def _merge(l):
+ return ''.join(l).strip()
+def _next(l):
+ sect = deque()
+ while l and not l[0].strip().startswith('$'):
+ sect.append(l.popleft())
+ if not l:
+ return (('TRAIL', _merge(sect)), l)
+ name = l.popleft().strip()[1:]
+ sect = _merge(sect)
+ return ((name, sect), l)
+def parse(s):
+ l = deque(s.splitlines(True))
+ meta = dict()
+ sects = OrderedDict()
+ while l and l[0].strip().startswith('$'):
+ s = shlex.split(l[0][1:])
+ meta[s[0]] = s[1:]
+ l.popleft()
+ while l:
+ s, l = _next(l)
+ sects[s[0]] = s[1]
+ return Meta(sects, meta)
diff --git a/mksite.sh b/mksite.sh
new file mode 100755
index 0000000..24aa43e
--- /dev/null
+++ b/mksite.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+./generate.py
+tar -caf site.tgz -C output .
+scp site.tgz erebus.the-tk.com:
+ssh -t erebus.the-tk.com webtools/updateweb.sh
diff --git a/output/.gitignore b/output/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/output/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/serve.sh b/serve.sh
new file mode 100755
index 0000000..95e578b
--- /dev/null
+++ b/serve.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+./generate.py -o /tmp/servepages -b "http://0.0.0.0:8000"
+cd /tmp/servepages || exit 1
+python -m http.server
diff --git a/templates/blog.html b/templates/blog.html
new file mode 100644
index 0000000..658f69d
--- /dev/null
+++ b/templates/blog.html
@@ -0,0 +1,7 @@
+{% extends "default.html" %}
+{% block content %}
+<h1>Posts</h1>
+<ul class="postlist">{% for post in page.posts %}
+ <li><time>{{ post.date|datefmt }}</time> | <a href="{{ '/' + post.location }}">{{ post.title }}</a>{% endfor %}
+</ul>
+{% endblock %}
diff --git a/templates/default.html b/templates/default.html
new file mode 100644
index 0000000..337cb20
--- /dev/null
+++ b/templates/default.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ {% block head %}
+ <title>{{ page.title }}</title>
+ <link rel="stylesheet" href="/style.css" />
+ <link rel="icon" type="image/png" sizes="32x32" href="/images/icon32x32.png" />
+ <link rel="icon" type="image/png" sizes="16x16" href="/images/icon16x16.png" />
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <meta name="description" content="{{ page.description }}" />
+ <meta name="author" content="Tomasz Kramkowski <tk@the-tk.com>" />
+ <meta name="keywords" content="{{ page.keywords }}" />
+ {% endblock %}
+ </head>
+ <body>
+ <main>
+ <header>
+ <nav>
+ <a href="{{ site.baseurl }}/">the-tk.com</a>
+ | <a href="{{ site.baseurl }}/blog.html">Blog</a>
+ | <a href="{{ site.baseurl }}/projects.html">Projects</a>
+ </nav>
+ </header>
+ <hr />
+ {% block content %}{% endblock %}
+ <hr />
+ <footer>
+ <a href="mailto:website-inquiries@the-tk.com">contact</a>
+ • <a href="https://github.com/EliteTK">github</a>
+ • <a href="https://the-tk.com/cgit">cgit</a>
+ • <a href="https://the-tk.com/archive">ML archive</a>
+ • <a href="http://www.catb.org/hacker-emblem/"><img class="icon" src="/images/glider-yellow.png" alt="Hacker Emblem" /></a>
+ • <a href="https://www.eff.org/"><img class="icon" src="/images/EFF.png" alt="EFF Logo" /></a>
+ • <a href="https://www.fsf.org/"><img class="icon" src="/images/GNU.png" alt="GNU Logo" /></a>
+ </footer>
+ </main>
+ <div id="copyright">
+ Copyright © Tomasz Kramkowski.
+ <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" src="/images/ccbysa.png" /></a><br />
+ All hosted work, unless otherwise specified, is available under a
+ <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a>
+ International License.<br />
+ </div>
+ </body>
+</html>
diff --git a/templates/error.html b/templates/error.html
new file mode 100644
index 0000000..23ba358
--- /dev/null
+++ b/templates/error.html
@@ -0,0 +1,5 @@
+{% extends "default.html" %}
+{% block content %}
+<h1>Error</h1>
+<h2>{{ page.code }} - {{ page.error }}</h2>
+{% endblock %}
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..c32a7fb
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,22 @@
+{% extends "default.html" %}
+{% block content %}
+<h1>Welcome</h1>
+
+<p>Welcome, this is my website, an under-maintained infodump. Hopefully you'll find something useful here.</p>
+
+<h2>Recent blogposts:</h2>
+<ul class="postlist">{% for post in page.posts %}
+ <li>
+ <article>
+ <header>
+ <h3>{{ post.title }}</h3>
+ </header>
+ {{ post.pre }}
+ <a href="/{{ post.location }}">Read more...</a>
+ <footer>
+ <time>{{ post.date|datefmt }}</time>
+ </footer>
+ </article>
+ </li>
+{% endfor %}</ul>
+{% endblock %}
diff --git a/templates/post.html b/templates/post.html
new file mode 100644
index 0000000..6cb47c3
--- /dev/null
+++ b/templates/post.html
@@ -0,0 +1,16 @@
+{% extends "default.html" %}
+{% block content %}
+<article>
+ <header>
+ <h1>{{ page.title }}</h1>
+ </header>
+ {{ page.content }}
+ <footer>{% if page.tags %}
+ <ul class="taglist">
+ <li>Tags:</li>{% for tag in page.tags %}
+ <li><a href="{{ '/tag/' + tag + '.html' }}">{{ tag }}</a></li>{% endfor %}
+ </ul>{% endif %}
+ <time>{{ page.date|datefmt }}</time>
+ </footer>
+</article>
+{% endblock %}
diff --git a/templates/project.html b/templates/project.html
new file mode 100644
index 0000000..15e4d9a
--- /dev/null
+++ b/templates/project.html
@@ -0,0 +1,16 @@
+{% extends "default.html" %}
+{% block content %}
+<h1>{{ page.title }}</h1>
+{{ page.content }}
+{% if page.source or page.ml %}<hr />
+<dl>
+{% if page.source %}<dt>Source</dt>
+ <dd><a href="{{ page.source }}">{{ page.source }}</a></dd>{% endif %}
+{% if page.ml %}<dt>Mailing list</dt>
+ <dd><a href="mailto:{{ page.ml }}@the-tk.com">{{ page.ml }}@the-tk.com</a>
+ (<a href="https://the-tk.com/archive/{{ page.ml }}/">archive</a>)</dd>{% endif %}
+{% if page.aur %}<dt>AUR</dt>
+<dd><a href="https://aur.archlinux.org/packages/{{ page.aur }}">{{ page.aur }}</a></dd>{% endif %}
+</dl>
+{% endif %}</article>
+{% endblock %}
diff --git a/templates/projects.html b/templates/projects.html
new file mode 100644
index 0000000..7405542
--- /dev/null
+++ b/templates/projects.html
@@ -0,0 +1,11 @@
+{% extends "default.html" %}
+{% block content %}
+<h1>Projects</h1>
+<ul class="projects">{% for project in page.projects %}
+ <li>
+ <h2>{{ project.name }}</h2>
+ <p>{{ project.description }}</p>
+ <a href="{{ '/' + project.location }}">More info...</a>
+ </li>{% endfor %}
+</ul>
+{% endblock %}
diff --git a/templates/tag.html b/templates/tag.html
new file mode 100644
index 0000000..47c5fa0
--- /dev/null
+++ b/templates/tag.html
@@ -0,0 +1,7 @@
+{% extends "default.html" %}
+{% block content %}
+<h1>Posts tagged - {{ page.tag }}</h1>
+<ul class="postlist">{% for post in page.posts %}
+ <li><time>{{ post.date|datefmt }}</time> | <a href="{{ '/' + post.location }}">{{ post.title }}</a>{% endfor %}
+</ul>
+{% endblock %}