The Comeback of Shortwave?
Published at 06:58 on 6 April 2022
Stories like this are very much not a surprise. How much longer until Voice of America and Radio Free Europe/Radio Liberty follow suit?
Musings of an anarchist misfit
Published at 06:58 on 6 April 2022
Stories like this are very much not a surprise. How much longer until Voice of America and Radio Free Europe/Radio Liberty follow suit?
Published at 21:02 on 3 April 2022
I collected this information about two years ago, intending to publish it here, yet never did. Before I lost track of it, I decided to do so this evening. Note that this information was correct as of two years ago; so there is a chance that some things have changed since then. (Though I am at present revisiting these topics, and so far I haven’t found any changes in what follows.)
I’ve been mostly a back-end programmer and command-line guy. That, plus inertia, has caused me to not bother with supporting graphical user interfaces in the code I write.
Until recently, that is. There’s a few ideas I’ve had rattling around in my head that would be useful for others, but many of those other people are not computer geeks and would not be interested in opening a Terminal or Command Prompt app just to run my command-line programs.
As a result, I’ve been learning how to make normal, “clickable” apps that a normal person would be able to run without extensive training and hand-holding. Might as well share that knowledge with others.
What follows is likely to be particularly useful to those who, like me, are using something other than the normal, approved tools to code their apps. In my case, I’m using Kotlin, because it’s a modern language with a powerful, expressive syntax and it runs under the Java virtual machine, making it much easier to port my code to different systems.
Yes, there are “standard” programs to do all of the following. Without very few exceptions, I have found them to be poorly documented and geared to C/C++ developers. I found that attempting to bend these tools to my will was sufficiently difficult and painful that it was easier to forget about them and just do it all myself, mostly from scratch.
To have an application that comes up as a clickable icon like all the other normal Gnome apps, one must install files in a number of places, primarily under /usr/share
. It’s something of a mess, as the files that define the presence of a given app are scattered here and there, not collected in one place as they are on a Mac.
The easiest way to cope with this state of affairs is to do what everyone else does: make a Debian package (Ubuntu is Debian under the hood). Thankfully, .deb
files are pretty simple: an ar
archive with three members:
debian-binary
control.tar.gz
control
(yes, control.tar.gz
contains a file named control
) file is the only mandatory one, though an md5sums
one is highly recommended. This must be the second member of the archive.data.tar.gz
/usr/share/program
it will be in here as usr/share/program
. This must be the third and final member of the archive.Note that all files must be stored with the correct ownership information (usually as root
, the superuser).
In order for a Linux application to look like a normal, clickable Gnome app, and for lintian
to not complain a lot about your package, you need to have a number of files installed (i.e. present in data.tar.gz
). For the purpose of this list, name refers to your application’s name, folded to lower case:
usr/bin/
nameusr/share/applications/
name.desktop
usr/share/doc/
name/changelog.gz
usr/share/doc/
name/copyright
/usr/share/common-licenses
, you should not include the full license terms in this file but instead end it with a reference to the common license.usr/share/icons/hicolor/48x48/apps/
name.png
theme. The name of this icon file must match the name of the icon described in the .desktop
file; for sanity’s sake, just use your application name.usr/share/
name.jar
and .class
files for a Java application will live here.usr/share/man/man1/
name.1.gz
It is best to use dpkg
to inspect a few .deb
files for programs similar to yours to get an idea of what you need to define. A good source of such files can be the system package cache, /var/cache/apt/arhives
.
Once you have a directory tree with the files you need, it is a simple enough matter to use tar
and ar
to create a .deb
file:
echo 2.0 > debian-binary
cd data
find * -type f -print0 | xargs -0 md5sum > ../control/md5sums
tar -c -z --owner=0 --group=0 -f ../data.tar.gz *
cd ../control
tar -c -z --owner=0 --group=0 -f ../control.tar.gz *
cd ..
ar r name.deb debian-binary control.tar.gz data.tar.gz
After creating your .deb package, it is strongly recommended that you use lintian --info
to check it. In general, you should be concerned about anything flagged at the E
(error) level, and at least make an effort to reduce the number of W
(warning) level messages that lintian
reports.
One thing I don’t worry about is complaints from lintian
about the manual pages not being compressed to the maximum level: I use an Apache Ant task, not the gzip
utility, to generate my compressed files, and it has no option to select maximum compression. It makes no difference to the system, and the amount of space saved by using maximum compression over the normal level is insignificant.
Welcome to the year 1967. You are at a keypunch machine preparing a data deck for an IBM 360 program. Be sure to follow the correct rules for which records get punched starting in which column, or you will be rewarded with lots of error codes IEBLINTIAN
later!
Your changelog deck consists of a series of cards, which contains groups of records which describe changes made to your program. Each group of records must begin with a card punched starting in column 1, of the following format:
name (version) distribution; urgency=urgency
Things in bold should be typed verbatim; things in italics should be replaced with something appropriate:
unstable
.low
.Following this card, you may optionally have a blank card. The details of the change are introduced by a card with an asterisk punched in column three (columns one and two must be blank); the remaining columns on this card describe the change. If describing the change takes more than a single card, subsequent continuation cards are punched starting in column five.
After the description comes an optional blank card, followed by the card defining the programmer and date. This is done by punching hyphens in columns 2 and 3; the card has the following overall format:
-- Joe Coder <joe@coder.com> Thu, 30 Apr 2020 13:16:43 -0700
Note that the e-mail address must be in angle brackets, and there must be two blanks separating it from the date, which must be punched in RFC2822 format (the same as reported by the date -R
command).
A Macintosh application (technically, an “application bundle”) is actually a directory whose name ends in .app
and which contains but a single subdirectory, Contents
. That subdirectory in turn must contain a number of files:
Contents/Info.plist
Info.plist
Java Notes” below. Apple provides a command-line program, /usr/libexec/PlistBuddy
, which can be useful when generating or reading this file.Contents/MacOS/
somethingCFBundleExecutable
key in Info.plist
.Contents/PkgInfo
APPL????
.Contents/Resources/
something.icns
CFBundleIconFile
key in Info.plist
.That’s it for the mandatory contents. Any directory whose name ends in .app and contains the above structure should be recognized as a clickable application by the Macintosh. It is, of course, common for applications to contain read-only data, which is also contained inside the app bundle. For example, .jar
and .class
files for Java applications can be stored in Contents/Java
. Applications can also use non-reserved keys in Info.plist
to store configuration information and other data.
Apple has a standard way of storing Java-specific information in Info.plist
, under a Java
element in the top-level dictionary. Unfortunately, using it will cause a Mac to attempt to run the app using a very old, Apple-customized Java runtime that isn’t even present on most Macs. Your users will see a dialog with a bunch of blather about the “legacy Java runtime” being needed, and even if they follow Apple’s suggestion and download that runtime, it is likely that won’t be able to run your application, because it is so obsolete.
Therefore, as Groucho Marx said about the doctor’s response to the patient who complained “It hurts when I do this,” don’t do that. I follow the Oracle convention of putting the entry-point class in JVMMainClassName
, a package-relative path to my Jar file in JVMClassPath
, a Java version specification in JVMVersion
, and any extra options to pass to the Java environment in a JVMOptions
array.
Actually, it doesn’t much matter. I could have come up with unique keys of my own (so long as they didn’t clash with any official Apple ones), and it would have worked just as well. MacOS is blissfully unaware of the significance of those JVM…
tags, and simply ignores them. They are meaningful only to my defined CFBundleExecutable
script, which has been coded to look in Info.plist
for some of its options.
Mac application icons are stored in .icns
files. These are actually a collection of multiple icons, defined for a variety of sizes. To create such a file, you must create a directory whose name ends in .iconset
, and populate it with PNG images containing your icon in various sizes, as described here. Then use iconutil
to generate a .icns
file; assuming your directory was named name.iconset
, you would type:
iconutil -c icns
name
A clickable app on Windows is simply an executable (.EXE
) file that contains an embedded icon which Windows will recognize and display.
If you create a jar file and set Main-Class in its manifest to point to the class containing your application’s entry point, Windows considers it to be an “executable jar” and will launch your application when you click on the jar file. That’s almost as good as a having a proper executable with an embedded icon, but it doesn’t have an embedded icon, so your app will display using the default icon that all jar files get.
The solution is to install Launch4j and use it to create a Windows executable with your icon of choice embedded in it. This is a free program, and I have found it to be well-documented.
If your application is sufficiently complex as to require a bunch of support files under Windows, then you will need to create a Microsoft Installer file. My apps have so far been simple enough not to require this, so I don’t have much help to offer in this regard yet.
Published at 17:17 on 31 March 2022
Much whining is made from Conservatives about how unfair the world is, because the Liberals got less votes than them, but still got to form a government. And now the NDP has agreed to enter into a confidence and supply agreement, maintaining the status quo for another three years. Doubly unfair!
Not quite. First off, let us review the results (via Wikipedia) of the most recent Federal election (only last year):
Party | % Vote | Seats | % Seats | Coefficient |
---|---|---|---|---|
Liberal | 32.62 | 157 | 46.44 | 1.42 |
Conservative | 33.74 | 121 | 35.79 | 1.06 |
Bloc Québécois | 7.64 | 32 | 9.46 | 1.23 |
New Democratic | 17.82 | 25 | 7.39 | 0.41 |
Green | 2.33 | 2 | 0.59 | 0.25 |
People’s | 4.94 | 0 | 0.00 | 0.00 |
(More about that mysterious “coefficient” column later; it’s important! But I digress.)
Anyhow, pay attention to the two parties that just entered into that supposedly “unfair” agreement: collectively, they got 50.44% of the vote. Barely a majority, but a majority nonetheless. Suddenly, this agreement is looking a lot less unfair. But wait, there’s more: the Greens are also a left-of-centre party, and the Bloc advocates a social-democratic flavor of Quebec nationalism. Add those votes and we are now up to 60.41% voting for centre-left politics of some sort.
But you would never realize that, given how much the Conservatives whine about how life is so unfair, because they got more votes than the Liberals did, yet don’t get to form a government. Now, they do have a little bit of a point; the Liberals are arguably over-represented. This is where my coefficient comes in; it is the ratio of the percentage of seats in the House of Commons to the percentage of the overall popular vote. A number greater than 1 indicates a party is over-represented, and a figure less than one indicates it is under-represented.
No party has a coefficient as high as the Liberals’ 1.42, so they are over-represented, no doubt about it. But the Conservatives are at 1.06, just about parity. If you want to see who’s getting the shaft, look at the NDP. A fair system would mean 60 NDP MP’s; instead, there are only 25. No other party falls so short in absolute numbers of seats, though the Greens and particularly the People’s Party fare worse percentage-wise.
There are definitely criticisms to be made about first-past-the-post, but to insinuate that it is undemocratically giving Canada a centre-left government is not one of them. A completely fair allocation of Commons seats, in line with popular vote percentages, would achieve the same basic outcome.
Published at 07:41 on 29 March 2022
There is a subset of the Left — probably not a majority, but definitely more than just a few people — that is very “both sides” about the war in Ukraine, refusing to see either side as being worthy of support. “Why are you siding with the US empire,” they ask.
My answer is: for the exact same reason I “sided with the Soviet empire” on the issue of East Timor in the 1980’s, when I first became aware of it: because that side was on the morally right side of that issue, defending a weaker nation that had been brutally invaded by a stronger one. The US Empire was strongly backing the invading nation, Indonesia, and the Soviet one was aiding the mostly leftist rebels fighting the invaders.
Just because both empires are seriously morally compromised does not mean that every last position either one takes on any issue taints that side of the issue beyond hope. That is not political strategy, that is oppositional defiant disorder. It is possible for a morally compromised empire — and all empires are evil — to nonetheless take a stand on a particular issue that is the morally correct one.
As morally compromised as the entire first Cold War was, it was also the case that the nations of Western Europe were much better places for human freedom than the nations of Eastern Europe. If you can’t acknowledge that plain fact, then you are simply not paying attention.
Once one got outside Europe, of course, the picture quickly got a lot murkier. The USA and its allies often supported brutal and kleptocratic colonial (and post-colonial neoimperialist) power structures. The USSR and its allies often opposed these same power structures (pity that the ones they set in place were seldom any better).
That the First World media generally ignores happenings in the Second and Third Worlds worked to the advantage of the US Empire, because, to reiterate, in Europe, the confrontation was also distinctly one between a world with more freedom and a world with less.
What this all calls for is nuance over simplicity. It is possible to acknowledge that what the West is doing in response to the invasion of Ukraine is generally what should be done, without going to the level of then concluding that anything the West does anywhere must be supported.
Published at 07:57 on 27 March 2022
Basically, because although NATO is on paper a multilateral organization, the USA is clearly and by far its most powerful and influential member, and therefore its de facto leader. Thus, any remarks of such character by a U.S. president help make Russia’s case that this whole thing is about a confrontation between NATO and Russia.
Since NATO is clearly more powerful than Russia and its allies, that, in turn, helps Putin reframe the narrative from one in which Russia is the aggressor to one in which Russia is being threatened by a yet more powerful alliance bent on ganging up against it. And the more Putin can do that, the more secure his position becomes.
Biden said what is obviously true: both Russia and the world as a whole would be better off without a fascist like Putin in charge. But by the very fact of saying it, he made that goal more difficult to achieve.
To reiterate: with great power comes great responsibility.
Published at 17:36 on 26 March 2022
“For God’s sake, this man [Putin] cannot remain in power.”
As much as I agree with the sentiment, the President of the United States has no business saying such things.
I can say such things… and get away with them. Biden cannot. I am just some random guy with a blog. Biden is President of the United States. As the old saying goes, with great power comes great responsibility.
Published at 08:23 on 25 March 2022
Any complete occupation would have been a very heavy lift for Russia even if they had done everything else right… and so far they have done just about everything wrong. So, assuming this all heads to what seems to be the obvious eventual conclusion, it means the invasion will have the exact opposite of its intended outcome.
The latter was for Ukraine to be cemented as an integral part of Russia. Instead, Ukraine (long an area with politics and culture that had been diverging from Moscow) will now have as part of its history a hard-fought war to preserve its independence from Russia. Wars of national liberation typically become part of the defining mythology of nations, and there no reason to suspect this will not be the case here.
Ukraine’s history also includes the Holodomor. Put those two together and there is a logical popular narrative emerging: Russia is the historic enemy of Ukraine.
Instead of being defined as an integral part of Russia, Ukraine is being defined by history as an irreconcilably distinct nation that is in no way part of Russia.
It will be, in this way, much like Finland, which had its own struggles for independence in the 20th century, one which involved several periods of conflict with first Russia then the USSR. Virtually nobody thinks of Finland as being the least bit Russian today.
Published at 21:24 on 24 March 2022
It’s going significantly better for Ukraine, and significantly worse for Russia, than I had imagined, and I had imagined it wouldn’t precisely go well for Russia. (This is, in fact, why I incorrectly predicted Russia would not attempt a full-scale invasion: because such an invasion was so unlikely to work out well for them.)
I am not going to strut around and make predictions of an imminent Ukranian victory any time soon, as much as I would like to see such a thing, and as much as some sources are predicting . Mostly, this is because the fog of war is very real: yes there are some encouraging reports that make it look like a big Russian retreat is imminent, but the accuracy of those reports is difficult to verify, and both sides lie in wars.
But still, I was expecting the formal government in Ukraine to fall pretty promptly. (I was then expecting an armed resistance to make life hell for the occupiers.) I certainly didn’t expect the Russian side to stall out so soon, and to still not have taken any major cities a month in. I would have in fact waved off any such predictions as Pollyanna-ish in the extreme.
It bears keeping in mind, however, that “going significantly better” than expected is still in the context of there being a war going on, and war is a very ugly thing.
As bleak as the latter point is, though, we are still in a much better place than if Putin had been rewarded, once again, with a very cheap price to be paid for his aggression. That would have not only encouraged Putin to launch follow-up actions, it would have probably encouraged other dictators, particularly the one in Beijing.
Published at 20:46 on 21 March 2022
One of the annoying things about any JVM language is that to run the result of compiling your code, you have to type something like:
java -cp somefile.jar domain.name.name2.SomeClass arg1 arg2 …
Or at best:
java -jar somefile.jar arg1 arg2 …
Wouldn’t it be great if you could just type the command name followed by arguments, like you can do with a compiled C or C++ program? The normal way to do this is to write a shell script and make it executable, but this is a tad clunky (now there are two files, the shell script and the JAR that it invokes). It would be nicer to have just a single executable.
Well, you can!
echo "#!/usr/bin/env java -jar" > somename
cat somefile.jar >> somename
chmod +x somename
And that is it! You now have an executable binary that is an archive of Java bytecode instead of native machine code. (Of course, it requires a suitable java interpreter to exist on your PATH.)
Best of all, while all of this sounds hackish, it is not just luck that a JAR file with some leading junk tacked on to it is still treated as a valid JAR file. No, this is basically guaranteed to work. You see, JAR files contain their header data at the end, not the beginning, and Java simply ignores all data earlier than what is described in the header.
And since the Macintosh is just a UNIX system under the hood, this trick works for Macs.
Published at 10:19 on 12 March 2022
Some people are claiming Russians support Putin’s war, citing polling data to back this up, but let’s think about what those polls are saying for a moment in the broader political context.
That context is the polling taking place in a country with basically no freedom of expression, a country where opposition media is banned, a country where peaceful protesters are arrested and tortured, a country where people are randomly accosted by police on the street so that messages on their smartphones can be checked for anti-Putin sentiments.
Imagine that you are a Russian. You know the risks involved in opposing the government. A random stranger approaches you on the street, or calls your phone, and claims to be an opinion researcher. S/he asks you if you support or oppose the most significant policy the government is currently engaged in. For all you know, he or she may in fact be a member of the FSB, Putin’s secret police. How do you answer?
It’s pretty obvious that all answers to any poll about issues of consequence in a country like Russia are answers given under significant duress.
As such, anything less than overwhelming support for the government is basically meaningless for purposes of concluding actual support. By “overwhelming” I mean 95% at minimum. Lukewarm support in the 60–70% range probably means significant overall opposition to the issue being polled about (and is probably as opposition-y as one can reasonably hope to see).
And the actual level of professed support for Putin’s war shown in that poll is… 58%!
Mark my words, the “majority” opinion expressed in that poll says the exact opposite of what a majority says in more normal circumstances.