I've done a lot of windows programming when I was using the system. I've been creating things I needed back then. Then I moved to use mostly (and then almost exclusively) linux and continued creating things I needed there. I still use linux a lot, of course, but I've also added another system to my everyday life (which, I must admit, I like) — Mac OS X.
I have to admit, there's no particular need in TFTP server and client on OS X, since it has command line tools for these needs, but still sometimes it is more convenient to fire up a nice GUI, especially when it comes to the server.
Anyway, to expand my horizons, learn a bit about the platform I use, dig a bit deeper into Objective-C, etc. I have ported the well-known PumpKIN TFTP daemon to Mac. (Icons were the hardest part).
This is the very 0.0 version, but it seems to work. And feedback is appreciated if anyone cares to try.
Love,
H
Склоняя на все лады разнообразные числительные к сожительству с разнообразными существительными во всевозможных падежах, я решил что человечество вправе об этом знать, а то и присоединиться. А то и сказать мне как я обосшибся.
Ежели кому-то хочется или нужно повторить подвиг, то этот кто-то, будучи не ленивым, может даже стырить код, это не трудно.
There are some things that are awfully out of fashion, that I still do. One of those things is maintaining server with its own configuration — personality, if you please. As opposed to maintaining the army of 125000 identical machines (yes, right, the same goes for humans).
That definitely doesn't take any enterprise grade configuration management system unless done in corporate environment, due to the lack of managers to keep confused. For tracking configuration files one can get away with widely available tools while nobody sees. In particular, I like putting files in git repository.
So I thought I'd put some snippets here for future reference and copy pasting.
First thing is add a nice alias for the root user (that guy who is in charge of breaking configuration):
alias cfgit='git --git-dir=/var/cfgit --work-tree=/'
Or even
eval $(echo "alias cfgit='git --git-dir=/var/cfgit --work-tree=/'" | tee -a /root/.bash_aliases)
(depending on the distribution). Then initialize and configure the /var/cfgit repository:
git init --bare --shared=0600 /var/cfgit cfgit config core.logallrefupdates true cfgit config user.name root@$(hostname) cfgit config user.email root@klever.net echo /\* >/var/cfgit/info/exclude
Done. Now one can add files to track before breaking the system.
cfgit add -f /etc/tobebroken/ cfgit commit -m 'stock tobebroken package configs'
cfgit add -f /usr/local/bin/mygreatscript cfgit commit -m 'my great script before I broke it'
and so forth…
Don't. Really. Unless you understand it.
I had an iPhoto library of some 30K pictures — some managed, some referenced and I wanted to consolidate the library — that is to copy the originals (a.k.a. masters) to the iPhoto Library for those photos that were copied with the appropriate preference off. Searching the web, looking at tools seemed to be of no help, so this is where I had to dig into iPhoto library guts and see if I can do it on my own.
It didn't take long to find that the Database/apdb/Library.apdb file and its RKMaster table have the information in question. Thank you, Apple, for adopting the sane standard for the databases, BTW. So, all I had to do is to copy files to the Masters directory (the subdirectory structure there is pretty straightforward — %Y/%m/%d/%Y%m%d-%H%M%S in terms of strftime) and update the database.
The shell script follows (note, that I used the script on linux, where the network storage resides, it may not be compatible with other environments out of the box). What makes it a bit longer than one might expect from the description above is that it puts no more than 2000 files in one directory.
#!/bin/bash ipl="/path/to/your/iPhoto Library.photolibrary" fvuuid="the-uuid-of-the-volume" fvpath="/path/to/the/volume/on/disk" dryrun="echo" cpln="ln" lf="/tmp/masterslist.$$" trap "rm $lf" EXIT sqlite3 "$ldb" "SELECT modelId,imagePath,originalFileName FROM RKMaster WHERE fileIsReference and fileVolumeUuid='$fvuuid'" >$lf \ || { echo "Couldn't fetch the list of images" ; exit 1 ; } while IFS=\| read mid ip ofn ; do [[ -r "$fvpath/$ip" ]] || { echo "$fvpath/$ip not found" ; continue; } [[ -n "$idir" && -e "$mpath/$idir/$ofn" ]] && idir='' [[ -z "$idir" || "$((++nf))" -ge 2000 ]] && { sleep $(((nf=0)+1)) ; idir="$(date +%Y/%m/%d/%Y%m%d-%H%M%S)" ; $dryrun mkdir -p "$mpath/$idir" ; } $dryrun $cpln -v "$fvpath/$ip" "$mpath/$idir/$ofn" || { echo "failed to $cpln $fvpath/$ip to $mpath/$idir/$ofn" ; exit 1; } $dryrun sqlite3 "$ldb" "UPDATE RKMaster SET fileVolumeUuid=NULL, fileIsReference=0, imagePath='$idir/$ofn' WHERE modelId=$mid" \ || { echo "failed to update database to reflect copy of $fvpath/$ip to $mpath/$idir/$ofn" ; exit 1; } done <$lf
Bold parts are the parameters to be modified. To get the uuid of the source volume one needs to peek into the database. It's the second column of the sqlite3 Database/apdb/Library.apdb "SELECT * FROM RKVolume" output.
And again. If you don't understand, don't do it. At any rate, backup what is there to backup. And don't hold it against me if you fail.
Not really a breakthrough, but the amount of small changes justifies a release. The new iii now consumes less memory when calculating integrity digest, accepts all files the card is willing to send and complains better when being wronged (the latter is only important if you haven't got it to work yet).
Love,
H
This is the old config snippet I am about to copy from one config to another and, while I'm at it, I thought I'd put it here for future reference.
The good thing about this approach is that almost the whole thing is completely done in the config file and requires almost no setup elsewhere. The bad thing is that I don't think it will perform well on high load. On my MX with approximately 10K incoming connections a day it performs alright.
So, this is how it's done. Exim needs to be compiled with sqlite support, of course. First step is to initialize the database with this table:
CREATE TABLE greylist ( gl_mailid text NOT NULL, gl_hostid text NOT NULL, gl_ctime integer NOT NULL DEFAULT ( strftime('%s','now') ), gl_atime integer NOT NULL DEFAULT ( strftime('%s','now') ), gl_btime integer NOT NULL DEFAULT ( strftime('%s','now') ), gl_ptime integer, gl_blocked integer DEFAULT 1, gl_passed integer DEFAULT 0, PRIMARY KEY (gl_mailid,gl_hostid) );
Then put this (or similar)
GREYDB=/var/lib/exim4/greylist.db
line into main section of exim configuration.
This acl does the whole thing:
acl_greylist: warn set acl_c_gl_mailid = $sender_address+$local_part@$domain set acl_c_gl_hostid = $sender_host_address+$sender_helo_name set acl_c_gl = ${lookup sqlite {GREYDB select *, \ strftime('%s','now')-gl_atime as sincea, strftime('%s','now')-gl_ctime as sincec from greylist \ where gl_mailid='${quote_sqlite:$acl_c_gl_mailid}' and gl_hostid='${quote_sqlite:$acl_c_gl_hostid}'; \ }} # defer strangers defer condition = ${if eq {$acl_c_gl}{} {true}{false}} set acl_c_nothing = ${lookup sqlite {GREYDB insert into greylist (gl_mailid,gl_hostid) VALUES \ ('${quote_sqlite:$acl_c_gl_mailid}','${quote_sqlite:$acl_c_gl_hostid}'); }} set acl_c_gl_message = Come back in some 10 minutes, stranger # accept passers accept condition = ${if >{${extract{gl_passed}{$acl_c_gl}}}{0} {true}{false}} set acl_c_nothing = ${lookup sqlite {GREYDB update greylist SET gl_passed=gl_passed+1, gl_atime=strftime('%s','now') \ where gl_mailid='${quote_sqlite:$acl_c_gl_mailid}' and gl_hostid='${quote_sqlite:$acl_c_gl_hostid}'; \ }} # accept after 12 mins of silence or 3 hours of knocking accept condition = ${if or{\ {>{${extract{sincea}{$acl_c_gl}}}{720}}\ {>{${extract{sincec}{$acl_c_gl}}}{10800}}\ }{true}{false}} set acl_c_nothing = ${lookup sqlite {GREYDB update greylist SET gl_atime=strftime('%s','now'), gl_passed=gl_passed+1, \ gl_ptime=coalesce(gl_ptime,strftime('%s','now')) \ where gl_mailid='${quote_sqlite:$acl_c_gl_mailid}' and gl_hostid='${quote_sqlite:$acl_c_gl_hostid}'; \ }} defer set acl_c_nothing = ${lookup sqlite {GREYDB update greylist SET gl_atime=strftime('%s','now'), gl_blocked=gl_blocked+1, \ gl_btime=strftime('%s','now') \ where gl_mailid='${quote_sqlite:$acl_c_gl_mailid}' and gl_hostid='${quote_sqlite:$acl_c_gl_hostid}'; \ }} set acl_c_gl_message = Come back in some 10 minutes, buddy
Finally, somewhere in acl_check_rcpt it would make sense to call the thing. Something like this:
warn acl = acl_greylist
So the only thing left is a daily cleanup:
DELETE FROM greylist WHERE 3600*24*gl_passed < (strftime('%s','now')-gl_atime);
And, unless I am mistaken (which is not completely unlikely) the greylisting setup is complete.
I'd even go as far as irresponsibly risking a generalization and hypothesizing that the sample provided is not just an isolated case, but does picture the state of the affairs in the infographics industry for the curious reader rather accurately.
First, I tried wifi. Joikuspot has a nice UI, successfully drains battery and fries phone and everything in contact therewith. Unfortunately, most of the time the success is limited to the aforementioned achievements. Mobilehotspot's success is pretty much limited to Joikuspot's one with the exception of cool UI and addition of succeeding in making me install the power kernel. So, I thought I'd rather look elsewhere.
Then, I tried Bluetooth DUN. It's easy and it works. But then you're forced to chose between computer and phone. So, I thought I'd see into other options.
And I only knew of one (USB being too wiresome), which is Bluetooth PAN. Having iptables-enabled kernel already (thanks to mobile hotspot), that really seemed to be an option. And actually turned out to be one. So I better write down the steps I took in case I'll have to reproduce it.
First, I went into /etc/bluetooth/main.conf and removed network from DisabledPlugins option value. Actually, on a second thought I've just commented out the line. I don't know when bluetoothd rereads the configuration file, so I SIGHUPed it.
Then, in Mac's system preferences, I dived into bluetooth part and updated device services for N900. Then I jumped into network part of system preferences, created Bluetooth PAN interface for the device and in advanced section specified manually 192.168.15.15 ip address with 192.168.15.19 router (don't ask why these numbers, they are just cool and if you're going to follow me, use your imagination!)
Then I went back to Nokia shell and added configuration to /etc/network/interfaces:
auto bnep0 iface bnep0 inet static address 192.168.15.19 netmask 255.255.255.0 pre-up sh -c "/usr/sbin/iptables -t nat -F ; /usr/sbin/iptables -t nat -A POSTROUTING -s 192.168.15.0/24 ! -d 192.168.15.0/24 -j MASQUERADE ; echo 1 >/proc/sys/net/ipv4/ip_forward"
And found out that for whatever reason it's not run. Instead of figuring this out I've just forced it by creating a /etc/udev/rules.d/50-bnep.rules file:
KERNEL=="bnep0", ACTION=="add", RUN+="/bin/sh -c '/sbin/ifup -f %k'" KERNEL=="bnep0", ACTION=="remove", RUN+="/bin/sh -c '/sbin/ifdown -f %k'"
Now when I want to access internet via Nokia, I turn bluetooth on, select 'Connect to Network' for Nokia from my Mac's bluetooth menu, and make sure phone itself is connected to the net.
If you can read this, it works for me. It probably won't work for you and you don't care, because most likely you have no N900, anyway.
Мазепа меняет фамилию на Сергей Грядущий. Глуп ты, Грядущий, вот что я тебе скажу.
Илья Ильф, Записные книжки
Есть у меня один интересный документ — старая ксерокопия старых вырезок из старых газет со старым, от руки написанным заголовком «Перемена фамилий и имен. Конец 20-х годов XX в.», вот таким:
И, надо сказать, так оно и есть. Именно об этих самых переменах и идёт речь. Ведь с одной стороны, каждый мог сменить свою фамилию, а с другой — об этом нужно было напечатать объявление в газете. Как заметил по этому поводу Лев Успенский, в «тебе и твоём имени»: тот, кто внимательно за этим следил, удивлялся многому. Не скажу, чтоб я следил за этим достаточно внимательно, чтобы удивляться, но чтение занимательное, чтобы не сказать… да ладно, скажу — захватывающее! Это вам не пейджеры за утренним кофе читать.
В общем, решил я, что негоже сидеть на таком сокровище и ни с кем не делиться. И, как могу, делюсь. С картинками для пущего душевного трепета. И, кроме трепета, ежели я что не разобрал или разобрал неправильно, а ты, прохожий, разобрал и, к тому же, правильно, то…
Вот они, касатики. Не все одинаково равны, но некоторые весьма…
Вы уже заметили? Или всё ещё думаете?
Have you noticed already? Or are you still thinking?