Ali's Hive Mind |
![]() |
February 04, 2012 [Saturday Morning Breakfast Cereal (updated daily)]

Hey geeks! Sorry about the slow load times. We're having some sort of server issue that hasn't been resolved yet.
On the plus side, only 2 more days until we go back to weekly SMBC Theater sketches. Check out our fancy new website!
February 03, 2012 [Saturday Morning Breakfast Cereal (updated daily)]

Hey geeks! SMBC Theater is going weekly again starting on Monday! Don't forget to subscribe for updates. Woop!
Stop ACTA in Europe, February 11th [Recent blog posts]
Last week we told you of the ongoing move in Europe against ACTA — now coordinated protests are taking place across Europe on February 11th, and here's how you can get involved.
Read 'Signed, not sealed' and contact your country's Members of the European Parliment
If you're not in Europe, please help spread the word to people who are. Defeating it in Europe is the first step to ending it once and for all.
For a refresher on why ACTA threatens free software, see http://www.fsf.org/campaigns/acta and the impact of ACTA on medicines.
Thank you for speaking up against ACTA,
Matt, Josh and John
more on ghc filename encodings [see shy jo]
My last post missed an important thing about
GHC 7.4's handling of encodings for FileName. It can in fact be safe to use
FilePath to write a command like rm. This is because GHC internally uses
a special encoding for FilePath data, that is documented to allow
"arbitrary undecodable bytes to be round-tripped through it". (It seems to
do this by encoding the undecodable bytes as very high unicode code
points.) So, when presented with a filename that cannot be decoded using
utf-8 (or whatever the system encoding is), it still handles it, and using
the resulting FilePath will in fact operate on the right file. Whew!
Moral of the story is that if you're going to be using GHC 7.4 to read or write filenames from a pipe, or a file, you need to arrange for the Handle you're reading or writing to use this special encoding too. I use this to set up my Handles:
import System.IO
import GHC.IO.Encoding
import GHC.IO.Handle
fileEncoding :: Handle -> IO ()
fileEncoding h = hSetEncoding h =<< getFileSystemEncoding
Even if you're only going to write a FilePath to stdout, you need to do this. Otherwise, your program will crash on some filenames! This doesn't seem quite right to me, but I hesitate to file a bug report. (And this is not a new problem in GHC anyway.) If I did, it would have this testcase:
# touch "me¡"
# LANG=C ghc
Prelude> :m System.Directory
Prelude System.Directory> mapM_ putStrLn =<< getDirectoryContents "."
me*** Exception: <stdout>: hPutChar: invalid argument (invalid character)
Since git-annex reads lots of filenames from git commands and other places, I had to deal with this extensively. Unfortunatly I have not found a way to read Text from a Handle using the fileSystemEncoding. So I'm stuck with slow Strings. But, it does seem to work now.
PS: I found a bug in GHC 7.4 today where one of those famous Haskell immutable values seems to get well, mutated. Specifically a [FilePath] that is non-empty at the top of a function ends up empty at the bottom. Unless IO is done involving it at the top. Really. Hope to develop a test case soon. Happily, the code that triggered it did so while working around a bug in GHC that is fixed in 7.4. Language bugs.. gotta love em.
Adventures in parsing C: ASTs for switch statements [Eli Bendersky's website]
Last week I received an email from a user of pycparser that mentioned the strange AST that results when pycparser parses a switch statement.
Let’s take the following snippet of C code for example. Don’t look for semantic sense in it – it’s just used to test the parser:
switch (myvar) {
case 10:
k = 10;
p = k + 1;
return 10;
case 20:
case 30:
return 20;
default:
break;
}
And the AST pycparser was generating for this code:
Switch:
ID: myvar
Compound:
Case:
Constant: int, 10
Assignment: =
ID: k
Constant: int, 10
Assignment: =
ID: p
BinaryOp: +
ID: k
Constant: int, 1
Return:
Constant: int, 10
Case:
Constant: int, 20
Case:
Constant: int, 30
Return:
Constant: int, 20
Default:
Break:
There are two problems here:
Since the parser follows the C grammar pretty closely, I immediately went to look into the C99 standard, and indeed, this is exactly the parse tree that it mandates. Here’s the relevant portion of the language grammar (from section A.2.3):
(6.8) statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
(6.8.1) labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
Note that a case (and default, which is equivalent to case in this whole discussion) must be followed by one, and only one other statement. This explains why pycparser parses the code above the way it does.
However, the goal of pycparser is not to generate a parse tree. It is to generate an abstract syntax tree (AST), which follows the language semantics rather than its grammar. Hey, I already wrote about this stuff!
So today I fixed this part of pycparser, by adding a dedicated AST transformation after parsing a switch statement. The transformation isn’t really complicated, and the AST pycparser generates now is much friendlier. Here it is, for the same code:
Switch:
ID: myvar
Compound:
Case:
Constant: int, 10
Assignment: =
ID: k
Constant: int, 10
Assignment: =
ID: p
BinaryOp: +
ID: k
Constant: int, 1
Return:
Constant: int, 10
Case:
Constant: int, 20
Case:
Constant: int, 30
Return:
Constant: int, 20
Default:
Break:
As you can see, the problems mentioned above were fixed. This fix is available in the pycparser Mercurial repository and will be part of the next release.
Related posts:
Listen to Your Community, But Don't Let Them Tell You What to Do [Coding Horror]
You know how interviewers love asking about your greatest weakness, or the biggest mistake you've ever made? These questions may sound formulaic, maybe even borderline cliche, but be careful when you answer: they are more important than they seem.
So when people ask me what our biggest mistake was in building Stack Overflow I'm glad I don't have to fudge around with platitudes. I can honestly and openly point to a huge, honking, ridiculously dumb mistake I made from the very first day of development on Stack Overflow – and, worse, a mistake I stubbornly clung to for a solid nine month period after that over the continued protestations of the community. I even went so far as to write a whole blog post decrying its very existence.
For the longest time, I had an awfully Fight Club-esque way of looking at this: the first rule of Stack Overflow was that you didn't discuss Stack Overflow! After all, we were there to learn about programming with our peers, not learn about a stupid website. Right?
I didn't see the need for a meta.
Meta is, of course, the place where you go to discuss the place. Take a moment and think about what that means. Meta is for people who care so deeply about their community that they're willing to go one step further, to come together and spend even more of their time deciding how to maintain and govern it. So, in a nutshell, I was telling the people who loved Stack Overflow the most of all to basically … f**k off and go away.
As I said, not my finest hour.
In my defense, I did eventually figure this out, thanks to the continued prodding of the community. Although we'd used an external meta site since beta, we eventually launched our very own meta.stackoverflow in June 2009, ten months after public beta. And we fixed this very definitively with Stack Exchange. Every Stack Exchange site we launch has a meta from day one. We now know that meta participation is the source of all meaningful leadership and governance in a community, so it is cultivated and monitored closely.
I also paid penance for my sins by becoming the top user of our own meta. I've spent the last 2 years and 7 months totally immersed in the morass of bugs, feature requests, discussions, and support that is our meta. As you can see in my profile, I've visited meta 901 unique days in that time frame, which is disturbingly close to every day. I consider my meta participation stats a badge of honor, but more than that, it's my job to help build this thing alongside you. We explicitly do everything in public on Stack Exchange – it's very intentionally the opposite of Ivory Tower Development.
Along the way I've learned a few lessons about building software with your community, and handling community feedback.
Let's get this out of the way immediately. Sturgeon's Law can't be denied by any man, woman, child … or community, for that matter. Meta community, I love you to death, so let's be honest with each other: most of the feedback and feature requests you give us are just not, uh, er … actionable, for a zillion different reasons.
But take heart: this means 10% of the community feedback you'll get is awesome! I guarantee you'll find ten posts that are pure gold, that have the potential to make the site clearly better for everyone … provided you have the intestinal fortitude to look at a hundred posts to get there. Be prepared to spend a lot of time, and I mean a whole freaking lot of time, mining through community feedback to extract those rare gems. I believe every community has users savvy enough to produce them in some quantity, and they're often startlingly wonderful.
You should immediately triage the feedback and feature requests you get into two broad buckets:
We need power windows in this car!
or
We need a truck bed in this car!
The former is, of course, a reasonable thing to request adding to a car, while the latter is a request to change the fundamental nature of the vehicle. The malleable form of software makes it all too tempting to bolt that truck bed on to our car. Why not? Users keep asking for it, and trucks sure are convenient, right?
Don't fall into this trap. Stay on mission. That car-truck hybrid is awfully tempting to a lot of folks, but then you end up with a Subaru Brat. Unless you really want to build a truck after all, the users asking for truck features need to be gently directed to their nearest truck dealership, because they're in the wrong place.
It always depressed me to see bug trackers and feedback forums with thousands of items languishing there in no man's land with no status at all. That's a sign of a neglected community, and worse, a dishonest relationship with the community. It is sadly all too typical. Don't do this!
I'm not saying you should tell your community that their feedback sucks, even when it frequently does. That'd be mean. But don't be shy about politely declining requests when you feel they don't make sense, or if you can't see any way they could be reasonably implemented. (You should always reserve the right to change your mind in the future, of course.) Sure, it hurts to be rejected – but it hurts far more to be ignored. I believe very, very strongly that if you're honest with your community, they will ultimately respect you more for that.
All relationships are predicated on honesty. If you're not willing to be honest with your community, how can you possibly expect them to respect you … or continue the relationship?
It's tempting to take meta community requests as a wholesale template for development of your software or website. The point of a meta is to listen to your community, and act on that feedback, right? On the contrary, acting too directly on community feedback is incredibly dangerous, and the reason many of these community initiatives fail when taken too literally. I'll let Tom Preston-Werner, the co-founder of GitHub, explain:
Consider a feature request such as “GitHub should let me FTP up a documentation site for my project.” What this customer is really trying to say is “I want a simple way to publish content related to my project,” but they’re used to what’s already out there, and so they pose the request in terms that are familiar to them. We could have implemented some horrible FTP based solution as requested, but we looked deeper into the underlying question and now we allow you to publish content by simply pushing a Git repository to your account. This meets requirements of both functionality and elegance.
Community feedback is great, but it should never be used as a crutch, a substitute for thinking deeply about what you're building and why. Always try to identify what the underlying needs are, and come up with a sensible roadmap.
Half of community relationships isn't doing what the community thinks they want at any given time, but simply being there to listen and respond to the community. When the co-founder of Stack Exchange responds to your meta post – even if it wasn't exactly what you may have wanted to hear – I hope it speaks volumes about how committed we are to really, truly building this thing alongside our community.
Regardless of whether money is changing hands or not, you should love discovering some small gem of a community request or bugfix on meta that makes your site or product better, and swooping in to make it so. That's a virtuous public feedback loop: it says you matter and we care and everything just keeps on getting better all in one delightful gesture.
And isn't that what it's all about?
| [advertisement] What's your next career move? Stack Overflow Careers has the best job listings from great companies, whether you're looking for opportunities at a startup or Fortune 500. You can search our job listings or create a profile and let employers find you. |
February 02, 2012 [Saturday Morning Breakfast Cereal (updated daily)]

Indulge me.
I'm starting to finally climb back in the saddle after about 2 weeks of travel and moving. So, the nerd blog is back in swing. Woop!
unicode ate my homework [see shy jo]
I've just spent several days trying to adapt git-annex to changes in ghc 4.7's handling of unicode in filenames. And by spent, I mean, time withdrawn from the bank, and frittered away.
In kindergarten, the top of the classrom wall was encircled by the aA bB cC of the alphabet. I'll bet they still put that up on the walls. And all the kids who grow up to become involved with computers learn that was a lie. The alphabet doesn't stop at zZ. It wouldn't all fit on a wall anymore.
So we're in a transition period, where we've all learnt deeply the alphabet, but the reality is much more complicated. And the collision between that intuitive sense of the world and the real world makes things more complicated still. And so, until we get much farther along in this transition period, you have to be very lucky indeed to not have wasted time dealing with that complexity, or at least having encountered Mojibake.
Most of the pain centers around programming languages, and libraries, which are all at different stages of the transition from ascii and other legacy encodings to unicode.
My most recent pain is because the haskell GHC compiler is moving along in the transition, getting closer to the end. Or at least finishing the second 80% and moving into the third 80%. (This is not a quick transition..)
The change involves filename encodings, a situation that, at least on unix systems, is a vast mess of its own. Any filename, anywhere, can be in any encoding, and there's no way to know what's the right one, if you dislike guessing.
Haskell folk like strongly typed stuff, so this ambiguity about what type
of data is contained in a FilePath type was surely anathama. So GHC is
changing to always use UTF-8 for operations on FilePath.
(Or whatever the system encoding is set to, but let's just assume it's
UTF-8.)
Which is great and all, unless you need to write a Haskell program
that can deal with arbitrary files. Let's say you want to delete
a file. Just a simple rm. Now there are two problems:
rm throws an exception.FilePath is loaded, it's been decoded to unicode characters.
In order to call unlink, these have to be re-encoded to get a
filename. Will that be the same bytes as the input filename and the
filename on disk? Possibly not, and then the rm will delete the wrong
thing, or fail.But haskell people are smart, so they thought of this problem, and provided
a separate type that can deal with it. RawFilePath hearks back to
kindergarten; the filename is simply a series of bytes with no encoding.
Which means it cannot be converted to a FilePath without encountering the
above problems. But does let you write a safe rm in ghc 4.7.
So I set out to make something more complicated than a rm, that still needs
to deal with arbitrary filename encodings. And I soon saw it would be
problimatic. Because the things ghc can do with RawFilePaths are limited.
It can't even split the directory from the filename. We often do need to
manipulate filenames in such ways, even if we don't know their encoding,
when we're doing something more complicated than rm.
If you use a library that does anything useful with FilePath, it's not
available for RawFilePath. If you used standard haskell stuff like
readFile and writeFile, it's not available for RawFilePath either.
Enjoy your low-level POSIX interface!
So, I went lowlevel, and wrote my own RawFilePath versions of pretty much
all of System.FilePath, and System.Directory, and parts of MissingH
and other libraries. (And noticed that I can understand all this Haskell
code.. yay!) And I got it close enough to working that, I'm sure,
if I wanted to chase type errors for a week, I could get git-annex, with
ghc 4.7, to fully work on any encoding of filenames.
But, now I'm left wondering what to do, because all this work is
regressive; it's swimming against the tide of the transition. GHC's
change is certainly the right change to make for most programs, that are
not like rm. And so most programs and libraries won't use RawFilePath.
This risks leaving a program that does a fish out of water.
At this point, I'm inclined to make git-annex support only unicode (or the
system encoding). That's easy. And maybe have a branch that uses
RawFilePath, in a hackish and type-unsafe way, with no guarantees
of correctness, for those who really need it.
Previously: unicode eye chart wanted on a bumper sticker abc boxes unpacking boxes
Android Security Update [Android Developers Blog]
Recently, there’s been a lot of news coverage of malware in the mobile space. Over on our Mobile blog, Hiroshi Lockheimer, VP of Android engineering, has posted Android and Security. We think most Android developers will find it interesting reading.
New Social APIs in Android ICS [Android Developers Blog]
[This post is by Daniel Lehmann, Tech Lead on the Android Apps team. — Tim Bray]
[We’re trying something new; There’s a post over on Google+ where we’ll host a discussion of this article. Daniel Lehmann has agreed to drop by and participate. Come on over and join in!]
With Android Ice Cream Sandwich, we set out to build software that supports emotional connections between humans and the devices they carry. We wanted to build the most personal device that the user has ever owned.
The first ingredient in our recipe is to show users the people that they care about most in a magazine-like way. High-resolution photos replace simple lists of text.

The second ingredient is to more prominently visualize their friends’ activities. We show updates from multiple sources wherever a contact is displayed, without the need to open each social networking app individually.
Android is an open platform, and in Ice Cream Sandwich we provide a rich new API to allow any social networking application to integrate with the system. This post explains how apps like Google+ use these APIs, and how other social networks can do the same.
Since Eclair (Android 2.0), the system has been able to join contacts from different sources. Android can notice if you are connected to the same person and different networks, and join those into aggregate contacts.

Essential terms to understand throughout the remainder of this post are:
RawContact is a contact as it exists in one source, for example a friend in Skype.
Data rows exists for each piece of information that the raw contact contains (name, phone number, email address, etc.).
A Contact joins multiple raw contacts into one aggregate. This is what the user perceives as a real contact in the People and Phone apps.
A sync adapter synchronizes its raw contacts with its cloud source. It can be bundled with a Market application (examples: Skype, Twitter, Google+).
While users deal with contacts, sync adapters work with their raw contact rows. They own the data inside a raw contact, but by design it is left up to Android to properly join raw contact rows with others.
Contacts sync adapters have a special xml file that describes their content, which is documented in the Android SDK. In the following paragraphs, we’ll assume this file is named contacts.xml.
The Android SDK also contains the application SampleSyncAdapter (and its source code) that implements everything mentioned in here in an easy to understand way.
In Android versions prior to Honeycomb (3.0), contact photos used to be 96x96. Starting with ICS, they now have a thumbnail (which is the 96x96 version) and a display photo. The display photo’s maximum size can vary from device to device (On Galaxy Nexus and Nexus S, it is currently configured to be 256x256, but expect this to vary with future devices). The size as configured can be queried like this:
private static int getPhotoPickSize(Context context) {
// Note that this URI is safe to call on the UI thread.
Cursor c = context.getContentResolver().query(DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
new String[]{ DisplayPhoto.DISPLAY_MAX_DIM }, null, null, null);
try {
c.moveToFirst();
return c.getInt(0);
} finally {
c.close();
}
}This value is useful if you need to query the picture from the server (as you can specify the right size for the download). If you already have a high resolution picture, there is no need for any resizing on your side; if it is too big, the contacts provider will downsample it automatically.
Up until now, pictures were written using a ContentValues object, just like all the other data rows of the raw contact. While this approach is still supported, it might fail when used with bigger pictures, as there is a size limit when sending ContentValues across process boundaries. The prefered way now is to use an AssetFileDescriptor and write them using a FileOutputStream instead:
private static void saveBitmapToRawContact(Context context, long rawContactId, byte[] photo) throws IOException {
Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
Uri outputFileUri =
Uri.withAppendedPath(rawContactUri, RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
AssetFileDescriptor descriptor = context.getContentResolver().openAssetFileDescriptor(
outputFileUri, "rw");
FileOutputStream stream = descriptor.createOutputStream();
try {
stream.write(photo);
} finally {
stream.close();
descriptor.close();
}
}For best results, store uncompressed square photos and let the contacts provider take care of compressing the photo. It will create both a thumbnail and a display photo as necessary.
This API is available on API version 14+. For older versions, we recommend to fallback to the old method using ContentValues and assuming a constant size of 96x96.
The API for update streams is the biggest new addition for contacts in Ice Cream Sandwich. Sync adapters can now enrich their contact data by providing a social stream that includes text and photos.

This API is intended to provide an entry point into your social app to increase user engagement. We chose to only surface the most recent few stream items, as we believe that your social app will always be the best way to interact with posts on your network.

StreamItems rows are associated with a raw contact row. They contain the newest updates of that raw contact, along with text, time stamp and comments. They can also have pictures, which are stored in StreamItemPhotos. The number of stream items per raw contact has a limit, which on the current Nexus devices is set to 5, but expect this number to change with future devices. The limit can be queried like this:
private static int getStreamItemLimit(Context context) {
// Note that this URI is safe to call on the UI thread.
Cursor c = context.getContentResolver().query(StreamItems.CONTENT_LIMIT_URI,
new String[]{ StreamItems.MAX_ITEMS }, null, null, null);
try {
c.moveToFirst();
return c.getInt(0);
} finally {
c.close();
}
}When displayed in the People app, stream items from all participating raw contacts will be intermixed and shown chronologically.
The following function shows how to add a stream item to an existing raw contact:
private static void addContactStreamItem(Context context, long rawContactId, String text,
String comments, long timestamp, String accountName, String accountType){
ContentValues values = new ContentValues();
values.put(StreamItems.RAW_CONTACT_ID, rawContactId);
values.put(StreamItems.TEXT, "Breakfasted at Tiffanys");
values.put(StreamItems.TIMESTAMP, timestamp);
values.put(StreamItems.COMMENTS, comments);
values.put(StreamItems.ACCOUNT_NAME, accountName);
values.put(StreamItems.ACCOUNT_TYPE, accountType);
context.getContentResolver().insert(StreamItems.CONTENT_URI, values);
}You can also specify an action that should be executed when a stream item or one of its photos is tapped. To achieve this, specify the receiving Activities in your contacts.xml using the tags viewStreamItemActivity and viewStreamItemPhotoActivity:
<ContactsAccountType
xmlns:android="http://schemas.android.com/apk/res/android"
viewStreamItemActivity="com.example.activities.ViewStreamItemActivity”
viewStreamItemPhotoActivity="com.example.activities.ViewStreamItemPhotoActivity">
<!-- Description of your data types -->
</ContactsAccountType>Update streams are available on API version 15+ and are intended to replace the StatusUpdate API. For previous versions, we recommend that you fall back to the StatusUpdates API, which only shows a single text item and no pictures.
Ice Cream Sandwich is the first version of Android that supports the “Me” contact, which is prominently shown at the top of the list of the new People app. This simplifies use-cases that used to be a multi-tap process in previous versions — for example, sharing personal contact data with another person or “navigating home” in a navigation app. Also it allows applications to directly address the user by name and show their photo.
The “Me” profile is protected by the new permissions READ_PROFILE and WRITE_PROFILE. The new functionality is powerful; READ_PROFILE lets developers access users’ personally identifying information. Please make sure to inform the user on why you require this permission.
The entry point to the new API is ContactsContract.Profile and is available on API version 14+.
Previously, connecting with users on a social network involved opening the respective social networking app, searching for the person and then connecting (“Friend”, “Follow” etc.). Ice Cream Sandwich has a much slicker approach: When looking at an existing contact in the People application, the user can decide to add this person to another network as well. For example, the user might want to follow a person on Google+ that they already have as a contact in Gmail.

Once the user taps one of the “Add connection” commands, the app is launched and can look for the person using the information that is already in the contact. Search criteria are up to the app, but good candidates are name, email address or phone number.
To specify your “Add connection” menu item, use the attributes inviteContactActivity and inviteContactActionLabel in your contacts.xml:
<ContactsAccountType
xmlns:android="http://schemas.android.com/apk/res/android"
inviteContactActivity="com.example.activities.InviteContactActivity"
inviteContactActionLabel="@string/invite_action_label">
<!-- Description of your data types -->
</ContactsAccountType>Be sure to use the same verb as you typically use for adding connections, so that in combination with your app icon the user understands which application is about to be launched.
The “Add connection” functionality is available on API version 14+.
High-resolution pictures need a lot of space, and social streams quickly become outdated. It is therefore not a good idea to keep the whole contacts database completely in sync with the social network. A well-written sync adapter should take importance of contacts into account; as an example, starred contacts are shown with big pictures, so high-resolution pictures are more important. Your network might also have its own metrics that can help to identify important contacts.
For all other contacts, you can register to receive a notification which is sent by the People app to all sync adapters that contribute to a contact whenever the contact’s detail page is opened. At that point, you can provide additional information. As an example, when the Google+ sync adapter receives this notification, it pulls in the high-resolution photo and most recent social stream posts for that user and writes them to the contacts provider. This can be achieved by adding the viewContactNotifyService attribute to contacts.xml:
<ContactsAccountType
xmlns:android="http://schemas.android.com/apk/res/android"
viewContactNotifyService="com.example.notifier.NotifierService">
<!-- Description of your data types -->
</ContactsAccountType>When this Intent is launched, its data field will point to the URI of the raw contact that was opened.
These notifications are available with API version 14+.
With Ice Cream Sandwich, we improved key areas around high resolution photos and update streams, and simplified the creation of new connections.
Everything outlined in here is done using open APIs that can be implemented by any network that wants to participate. We’re excited to see how developers take advantage of these new features!
Running your own Node-B [Dieter Spaar's blog]
Its now nearly 3 and a half year ago that I wrote the first "Proof-of-Concept" code to get the Siemens BS-11 GSM Basestation up and running. So I think it was time to start with 3G, now that LTE is being actively deployed. You also can sometimes find reasonable priced, used Node-Bs which makes getting access to the equipment possible. A Node-B is the 3G equivalent of a GSM BTS.
So I spent quite a lot of time spread of several months to get a Node-B up and running. Compared with the BS-11 this was a lot more difficult and required much more time. Of course the Air Interface is completely different, in my case I looked at WCDMA FDD so far, there a few more standards used in other parts of the world. Then you have to deal with a huge, different specification, the most important when dealing with a Node-B are NBAP (TS 25.433) and RRC (TS 25.331), around 3000 pages in total. NBAP, the Node-B Application Part, is used to configure the Node-B and do things like creating Radio Links (communication channels) to the phone. RRC, the Radio Resource Control, is the Layer-3 protocol for the control plane between the phone and the access network. It is responsible for accessing the network, setting up and releasing connections or paging a phone. Both NBAP and RRC make use of ASN.1 which makes things not necessarily easier ;-) There are a few more protocols on the lower layers involved like MAC (TS 25.321), RLC (TS 25.322) and FP (TS 25.435 and TS 25.427).
The Node-Bs I used can run "Iub over IP" (Iub is the interface between the Node-B and the RNC, similar to Abis in GSM between the BTS and BSC). Originally Iub is based on ATM which runs over E1/T1 or similar lines with higher data rates. However "Iub over ATM" adds a few more protocol layers for dealing with ATM and I really wanted to avoid this additional complexity. Not all Node-Bs can automatically do "Iub over IP", usually it requires an additional hardware option (interface card). When using "Iub over IP" you have to deal with protocols like UDP and SCTP which are much more convenient.
The current status is a very minimal implementation of something like an RNC to run the Node-B so that a phone can register on the network and do simple things like SMS on the control plane. No user plane like speech or data yet, but this is the next steps I plan to do. The code is not yet public but it will be when it gets more evolved.
There is still a lot left to research and experiment with. For example I haven't looked at things like HSPA yet, I completely ignore handover to other cells as there is only one cell in my experimental setup. So I am sure 3G will give a few more years of a very interesting field to play with before looking at LTE ;-)
You did your part, now it's our turn to do more for you! [News]
Even better, we also exceeded our "behind the scenes" goal, which was to sign up at least 400 new members over the two months. I'm really thrilled to welcome so many new supporters, including our 423 new associate members.
On behalf of everyone here at the FSF, I'd like to thank all of you who donated and joined, and all of you who helped promote the effort through your networks. The amount of response this year was incredibly gratifying, and makes me feel extremely optimistic about what we can get done in the year ahead.
I'd specifically like to thank Mark Holmquist, who referred 15 of those 423 new members all by himself, our intern emeritus Danny Piccirillo who went above and beyond in getting the word out, Max and the gang from reddit, and everyone who donated $500 or more to appear on our ThankGNU list.
We had a lot of fun writing the fundraiser pieces this year describing the work of the different staff members here at the FSF, and how we could get more done in each area with increased financial support. We didn't get a chance to write about everyone yet (like, ahem, me!), but we'll pick up where we left off next time. Thank you to all of you who wrote to us with encouraging comments about this series of articles — of course we always worry about annoying our supporters by being too pushy, so it was very good to hear that the articles were worthwhile reading.
Now that you've given us a vote of confidence to do more for you, it's time for us to get to it!
You can keep tabs on our work by signing up for our monthly Free Software Supporter newsletter (along with occasional interim updates), and subscribing to our blogs RSS feed.
I hope to see all of you in person at LibrePlanet this March in Boston! And for anyone who will be at FOSDEM this weekend, look me up.
529 – Proposition Joe [Luke Surl Comics]
To be honest, any girl who is aware of my Twitter account is likely to leave the relationship a long time before this stage..
Shmoocon 2012 [Kristin Paget's Blog]
In the absence of an “official” download link for these so far (although I’m sure they’ll be up on the Shmoocon page soon enough), my slides from Shmoocon this year. Seems it got a little press coverage and a whole bunch of attention on Twitter, so I figured I should get these out ASAP.
Hopefully video will be up soon but if anyone has questions about the talk in the meantime please ping me (ideally on twitter) and I’ll update the FAQ as and when I can.
FAQ:
What hardware / software were you using?
I used a Vivopay 4500 contactless card reader, an MSE-750 magstripe reader/writer, a Square dongle for my cellphone (on Android, not iPhone), and some code I wrote based on 3ricj‘s PwnPass code (no longer publicly available, afaik).
How did you get magstripe data from a contactless read?
The contactless reader spits out magstripe-formatted data as its intended mode of operation. I get valid Track1 / Track2 info (lacking only the name, which is usually “Valued Cardmember” or some such), which I just copy and paste to T1 / T2 on the MSR. There’s really not much to it – and yes, I’m processing credit card transactions without knowing the cardholder’s name.
Can you use the resultant card data online?
I get a valid cardnumber and expiry date (both usually the same as printed on the face of the card) and a single-use CVV value. If you can find somewhere online that’ll let you process a transaction with nothing but a card number and expiry date then yes you could, but otherwise you’re restricted to writing a magstripe and using that.
This is old news – XYZ did this years ago
I’m certainly not the first person to demo RFID vulnerabilities in payment cards. I haven’t heard of a full end-to-end demo before (RFID -> magstripe -> Square -> Profit!) but that doesn’t mean it’s not been done; I won’t be the last either as long as the industry keeps denying the problems. Now that it’s been irrefutably proven live on-stage that contactless fraud is possible I’m hoping that some of these issues can be addressed; if not don’t expect me to be the last person to talk about it either.
So what’s the deal with the CVV?
Credit cards have 3 CVV codes, one printed on the back of the card, a second encoded onto the magstripe, and a third from the RFID which changes with each read. Square (as well as some other combinations of PoS terminal + backend processor) is unable to tell the difference between an RFID transaction and a magstripe transaction, so as long as the CVV is valid (i.e. it’s being played back in-sequence with no repeats) the transaction goes through.
The One Button Mystique [Coding Horror]
I enjoy my iPhone, but I can't quite come to terms with one aspect of its design: Apple's insistence that there can be only ever be one, and only one, button on the front of the device.
I also own a completely buttonless Kindle Fire, and you'll get no argument from me that there should be at least one obvious "Jesus Handle" button on the front of any gadget. I do wonder why Amazon decided to make the Fire buttonless, when every other Kindle they ship has a home button. Amazon has a track record of making some awfully rough version 1.0 devices; I'm sure they'll add a home button in a version or two. And, hey, at only $199 I'm willing to cut them a little slack. For now.
Even Apple is no stranger to buttonless devices. Consider the oddly buttonless third generation iPod Shuffle, where you had to double and even triple click the controls on the headphones to do basic things like advance tracks. Oh, and by the way, this also made every set of headphones you own obsolete, at least for use with this model. The fourth gen shuffle rapidly switched back to physical controls on the device, and the fifth gen went to touch controls on the device, as expected.
Microsoft is just as guilty. I sometimes struggle with the otherwise awesome Xbox 360 Wireless Microphone. It has only a power button and some lights.
In its defense, for the most part it does just work when you pick it up and start singing (badly, in my case), but I admit to being slightly perplexed every time I have to sync it with an Xbox, or figure out what's going on with it. Can you blame me?
When you turn on the microphone, the built-in lights shine to display the microphone status as follows:
- Power on: lights flash green one time every second
- Connecting: lights flash green four times every second
- Connection complete: lights flash blue, and then stops
When your battery power is low, the built-in lights shine to display the battery charge status as follows:
- Low: Lights flash amber one time every three seconds
- Critical: Lights flash amber one time every second
When your microphone moves out of the wireless range of your console, the lights flash green one time every second. The lights can also change color together with supported game titles.
If we can agree that no buttons is clearly a bad idea, I think it follows that one button is problematic in its own way. I have the same issue with the single button on the iPhone that I do with the single button mouse – it may be OK-ish at the very beginning, but over time it leads to absurd, almost comical overloading of functionality. Consider how many different things the single button on the face of an iPhone now controls:
(diagram courtesy Andrew Durdin, source)
The iPhone home button? Why, it's easy! You have your choice of…
All of which have different meanings at different times, of course. In particular I spend a lot of time double-clicking to get to the active apps list, and I often mis-tap which kicks me over to the home screen. I have so many apps installed on my iPhone that search is the only rational way to navigate. This means I search a lot, which requires clicking once to get to the default home page, pausing, then clicking again. Sometimes I click too long, which is then detected as click-and-hold, and I get the voice search app which I am … er, not a fan of, to put it mildly.
I've gotten to the point where I dread using the home button on my iPhone because it Makes Me Think. And I get it wrong a significant percentage of the time. This isn't the way it's supposed to be.
You might be expecting me to turn into a rabid Windows Phone or Android fanboy about now and snarkily note how they get it right. I'm not sure they do. Either of them. They all manage to suck in their own special way.
When there's one button on the device, at least it's clear what that button is supposed to do, right? Well, sometimes.
There is one theme I agree with here – the clearly marked back button on both Android and Windows phones, just like a web browser. I mostly use my iPhone as a platform for the Internet, and the simplicity of the Internet is its primary strength: a collection of obvious things to click, and an easy, giant honking back button so you never get lost in its maze of twisty passages, all alike. It is true that browsers have a home button, but the latest versions of Chrome, Firefox, and Internet Explorer have all but pushed that home button off the UI in favor of the ginormous back button. While I'll tentatively agree that not all phone apps have to behave like the Internet, the Internet is becoming more and more of a platform for bona fide applications every day. The back button is a UI paradigm that works like gangbusters for webapps, and I'd argue strongly in favor of that being a hard button on a device.
But once you add three buttons, thinking starts to creep in again. Am I pressing the correct button? That's never good. And I don't even know what that third button is supposed to be on the Android phone! I could possibly be in favor of the hard search button on the Windows phone, I suppose, but I'd rather see good, consistent use of two buttons on the face of a device before willy-nilly adding Yet Another Button. I think there's a reason the industry has more or less standardized on a two-button mouse, for example. (Yes, there is that pesky middle button, but it's a nice to have, not an essential part of the experience.)
What about the one finger solution? Even with touch devices, one finger does not seem to be enough; there's a curious overloading of the experience over time.
On the iPad, there are a number of system-wide gestures, such as swiping left or right with four fingers to switch between apps. Four-finger swipes? That's convoluted, but imagine a virtual mixing console with horizontal sliders. Quickly move four of them at once...and you switch apps. Application designers have to work around these, making sure that legitimate input methods don't mimic the system-level gestures.
The worst offender is this: swipe down from the top of the screen to reveal the Notification Center (a window containing calendar appointments, the weather, etc.). A single-finger vertical motion is hardly unusual, and many apps expect such input. The games Flight Control and Fruit Ninja are two prime examples. Unintentionally pulling down the Notification Center during normal gameplay is common. A centered vertical swipe is natural in any paint program, too. Do app designers need build around allowing such controls? Apparently, yes.
Yes, our old friend overloading is now on the touch scene in spades: for all but the simplest use of a tablet, you will inevitably find yourself double-tapping, tapping and holding, swiping with two fingers, and so on.
Apple's done a great job of embodying simplicity and clean design, but I often think they go too far, particularly at the beginning. For example, the first Mac didn't even have cursor keys. Everything's a design call, and somewhat subjective, but like Goldilocks, I'm going to maintain that the secret sauce here is not to get the porridge too cold (no buttons) or too hot (3 or more buttons), but just right. I'd certainly be a happier iPhone user if I didn't have to think so much about what's going to happen when I press my home button for the hundredth time in a day.
| [advertisement] What's your next career move? Stack Overflow Careers has the best job listings from great companies, whether you're looking for opportunities at a startup or Fortune 500. You can search our job listings or create a profile and let employers find you. |
Android Developers on Google+ [Android Developers Blog]
[This post is by Reto Meier, Android Developer Relations Tech Lead. — Tim Bray]
I’ve been fortunate enough to be involved with Android since the 0.9 preview SDK was released to developers back in 2007. A lot has changed since then, but one thing that hasn’t is the rapid pace at which new tools, resources, and information have become available for us Android developers. Just look at the last few months.
In December Android Training launched, with its first set of classes designed to demonstrate the best practices behind building great Android Apps.
Earlier this month, the Android design site went live — offering a place to learn about the principles, building blocks, and patterns you need to make good design decisions when creating your Android app interfaces.

We’ve got a lot more planned in the coming year, so to help you keep abreast of all the latest Android developer news we’re launching the +Android Developers page on Google+!
One of my favourite things about Google+ is the quality of conversation around posts, so +Android Developers will focus on being a place for the people behind the Android developer experience, and Android developers all around the world, to meet and discuss the latest in Android app development.
We’ll be posting development tips, discussing updates to the SDK and developer tools, highlighting new Android training classes, and posting video and pics from Android developer events around the world.
We’ll also be using Google+ Hangouts to help us all interact even more closely. Starting with weekly broadcast office-hours on Hangouts On Air to answer Android development questions. These will happen every Wednesday at 2pm Pacific Time (10pm UTS) in Mountain View—expect to see these hangouts in more time zones as our teams in London, Sydney, and Tokyo get involved. Each hangout will be recorded for YouTube, so if you can’t join us live you won’t miss out.
It turns out that hangouts are a lot of fun, so we’ll be doing more of these that feature interviews with Google engineers and 3rd party Android app developers willing to share their tips and experiences.
We’re looking forward to interacting with you even more closely, so add us to your circles, join the conversation by commenting on posts, and join the hangouts. We can't wait to hear what you have to say.
Building Social Software for the Anti-Social [Coding Horror]
In November, I delivered the keynote presentation at Øredev 2011. It was the second and probably final presentation in the series I call Building Social Software for the Anti-Social.
I've spent almost four years thinking about the Q&A format, and these two presentations are the culmination of that line of thought. In them I present ten "scary ideas", ideas which are counterintuitive for most folks. These are the building blocks we used to construct Stack Overflow, and by extension, Server Fault, Super User, and the rest of the Stack Exchange network.
It's not the same experience as attending the actual live presentation, of course, but you can certainly get the gist of it by viewing the slides for these two presentations online:
The Øredev organizers hired ImageThink to draw each presentation on a whiteboard live on stage as it was presented. I was skeptical that this would work, but the whiteboard visualizations came out great for all the presentations. Here's the two whiteboard drawings ImageThink created during my presentation. (Yes, they had two artists on stage "live whiteboarding", one on the left side, and one on the right side.)
It's not a bad approximation of what was covered. If you're curious about live whiteboard visualizations, ImageThink posted a great set of links on their blog that I highly recommend.
After four years, we've mostly figured out what works and what doesn't work for our particular brand of low noise, high signal Q&A at Stack Exchange. But the title Social Software for the Anti-Social is only partially tongue in cheek. If you want to learn anything online, you have to design your software to refocus and redirect people's natural social group impulses, and that's what these presentations attempt to explain. I hope you enjoy them!
Update: Part II is now available as a full talk, with audio and video courtesy of GitHub. Watch it now!
| [advertisement] What's your next career move? Stack Overflow Careers has the best job listings from great companies, whether you're looking for opportunities at a startup or Fortune 500. You can search our job listings or create a profile and let employers find you. |
Some Basic Thoughts on GPL Enforcement [Bradley M. Kuhn's Blog ( bkuhn )]
I've had the interesting pleasure the last 36 hours to watch people debate something that's been a major part of my life's work for the last thirteen years. I'm admittedly proud of myself for entirely resisting the urge to dive into the comment threads, and I don't think it would be all that useful to do so. Mostly, I believe my work stands on its own, and people can make their judgments and disagree if they like (as a few have) or speak out about how they support it (as even more did — at least by my confirmation-biased count, anyway :).
I was concerned, however, that some of the classic misconceptions about GPL enforcement were coming up yet again. I generally feel that I give so many talks (including releasing one as an oggcast) that everyone must by now know the detailed reasons why GPL enforcement is done the way it is, and how a plan for non-profit GPL enforcement is executed.
But, the recent discussion threads show otherwise. So, over on Conservancy's blog, I've written a basic, first-principles summary of my GPL enforcement philosophy and I've also posted a few comments on the BusyBox mailing list thread, too.
I may have more to say about this later, but that's it for now, I think.
Announcing my third e-book "Perl One-Liners Explained" [good coders code, great reuse]
Hello ladies and gentlemen! I'm happy to announce my 3rd e-book called "Perl One-Liners Explained." This book is based on the "Famous Perl One-Liners Explained" article series that I wrote over the last 3 years and that has been read over 500,000 times!
I went through all the one-liners in the article series, improved explanations, fixed mistakes and typos, added a bunch of new one-liners, added an introduction to Perl one-liners and a new chapter on Perl's special variables.
The e-book has 111 pages and it explains 130 unique one-liners. Many of one-liners are presented in several different ways so the total number of one-liners in the book is over 200.
The e-book is divided into the following chapters:
Perl one-liners are small and awesome Perl programs that fit in a single line of code and they do one thing really well. These things include changing line spacing, numbering lines, doing calculations, converting and substituting text, deleting and printing certain lines, parsing logs, editing files in-place, doing statistics, carrying out system administration tasks, updating a bunch of files at once, and many more.
Perl one-liners will make you the shell warrior. You'll be able to do all these tasks in seconds. No kidding!
Let's take a look at several practical examples that you can easily do with one-liners. All these examples and many more are explained in the e-book.
I have also made the first chapter of the book, Introduction to Perl One-Liners, freely available. Please download the e-book preview to read it.
Example 1: Replace a string in multiple files at once
perl -p -i.bak -e 's/Config/config/g' conf1 conf2 conf3
Suppose you have 3 configuration files, and you discover that you made a mistake and need to replace all occurrences of Config to config. This one-liner does just that. It executes the s/Config/config/g that replaces all occurrences of Config with config on all lines. And since you're smart about it, you always do -i.bak to make backup files in case something goes wrong.
I explain the -i, -p, and -e arguments in the e-book in great detail.
Example 2: Generate a random 8 character password
perl -le 'print map { ("a".."z")[rand 26] } 1..8'
This one-liner generates and prints a random 8 character password. It uses the list range operator .. operator to produce all strings from "a" to "z", which is the alphabet. Then a random letter is chosen by rand 26 and this operation is repeated 8 times.
Example 3: URL-escape a string
perl -MURI::Escape -lne 'print uri_escape($string)'
Here we use the URI::Escape module from CPAN. It exports the uri_escape function that does URL-escaping.
You can install this module from CPAN by running perl -MCPAN -e'install URI::Escape' on the command line.
I have this one-liner as an alias actually for both URL-escaping and unescaping URL-escaping as it's such a common thing to do:
urlescape () { perl -MURI::Escape -lne 'print uri_escape($_)' <<< "$1" }
urlunescape () { perl -MURI::Escape -lne 'print uri_unescape($_)' <<< "$1"; }
Then I can do this in the shell:
$ urlescape "http://www.catonmat.net" http%3A%2F%2Fwww.catonmat.net $ urlunescape http%3A%2F%2Fwww.catonmat.net http://www.catonmat.net
Very useful!
Example 4: Print all lines from line 17 to line 30
perl -ne 'print if 17..30'
Here we use the binary flip-flop operator .. that becomes true when the input line number is 17, stays true while the line number is less than or equal to 30, and then becomes false. Combining the flip-flop operator with print if makes it print only lines 17-30.
Example 5: Remove all consecutive blank lines, leaving just one
perl -00pe0
I included this one-liner here in the examples just to show you how funny and obscure one-liners can get. This one-liner deletes all repeated blank lines from the input or from the given file. It does it by enabling the paragraph slurp mode through -00 command line argument, which reads the input paragraph-by-paragraph, rather than line-by-line, and prints the paragraphs. This way any number of blank lines between the paragraphs get ignored.
I explain this one-liner in more details in the e-book.
As I hope you can see, knowing how to write one-liners is very useful. It was one of my top priority tasks through the years to become very efficient in the shell. Literally every day when I'm programming, I have to do all kinds of data processing tasks, changing files, verifying output, doing quick calculations, parsing data, etc, and knowing Perl one-liners makes it really fast to get things done.
Now that I have written this e-book, you can become very efficient, too. Enjoy!
I prepared a free book preview that contains the first 13 pages of the book. It includes the table of contents, preface, introduction to Perl one-liners and the first page of the second chapter.
The price of the e-book is $9.95 and it can be purchased via PayPal:
After you have made the payment, my automated e-book processing system will send you the PDF e-book in a few minutes!
Help me spread the word about my new book! I prepared a special link that you can use to tweet about it:
I really love writing about programming and I have planned writing many more books. The next few are going to be a book on mastering vim, a practical guide on how to be anonymous on the web, and the catonmat book.
Enjoy the book and don't forget to leave comments about it! Ask me anything you wish and I'll help you out.
Also if you're interested, take a look at my other two e-books. The 1st one is called "Awk One-Liners Explained" and the 2nd one is called "Sed One-Liners Explained" They're written in a similar style as this e-book and they teach practical Awk and Sed through many examples.
Finally, if you enjoy my writing, you can subscribe to my blog, follow me on Twitter or Google+.
Defeating SOPA and PIPA Isn't Enough [Coding Horror]
SOPA and PIPA are two pieces of proposed legislation designed to "stop" Internet piracy… in the most hamfisted way imaginable. As Mitchell Baker explains:
Assume there's a corner store in your neighborhood that rents movies. But the movie industry believes that some or even all of the videos in that store are unauthorized copies, so that they're not being paid when people watch their movies. What should be done?SOPA/PIPA do not aim at the people trying to get to the store, or even the store itself. The solution under the proposed bills is to make it as difficult as possible to find or interact with the store:
- Maps showing the location of the store must be changed to hide it.
- The road to the store must be blocked off so that it is difficult to physically get to there.
- Directory services must delist the store’s phone number and address.
- Credit card companies would have to cease providing services to the store.
- Local newspapers would no longer be allowed to place ads for the video store.
- To make sure it all happens, any person or organization who doesn’t do this is subject to penalties. Even publishing a newsletter that tells people where the store is would be prohibited by this legislation.
Just substitute "corner store" with "website" and I think you can see where this is going. These bills are so rife with potential for abuse and misuse, so clearly dangerous to the very fabric of the Internet, that frankly I have a hard time getting worked up about them. The Internet is under constant siege by large companies, and will be for the forseeable future. This is nothing new. These bills will be defeated, because they must be.
Instead, I'm scratching my head and wondering how such boneheaded bills made it this far in Congress. I can think of a few reasons:
I often bemoan the state of Slacktivism on the internet, where changing your Facebook or Twitter picture is considered a valid and effective form of protest. But this time, I am happy to say, was indeed different.
Perhaps because of the obvious danger of these bills, geek websites and communities banded together weeks ago to protect themselves and the greater Internet. Like many other technical communities, we wrote about it on our blog, talked about it on our podcast, and even put up a little banner on Stack Overflow for a day. Users were encouraged to call, fax, and write their representatives in Congress and express their concerns. And they did, in droves! But outside of our technical geek ghettos, there was precious little mainstream coverage of this dangerous legislation.
That is, until major sites like Wikipedia, Google, and Craigslist joined the bandwagon today. Most notably, Wikipedia actually went dark for all of today, January 18th, rendering all of English language Wikipedia inaccessible. That turned the tide, and transformed SOPA/PIPA into something that average people would actually talk about and care about. There's no better way to raise awareness of the danger these bills pose than blacklisting one of the greatest resources the Internet has ever produced.
While SOPA/PIPA are still alive -- barely -- for now, I think it's safe to say that they are well on their way to defeat. I'm glad to be a part of that, however tiny, but I cannot in good conscience celebrate.
Yes, we likely succeeded in defeating these two specific bills and galvanizing the political will of major Internet communities, including our very own Stack Exchange. These are good and noble and just and necessary things. They are things to be proud of. But instead of celebrating, let's take this time to reflect and ask ourselves a deeper question: how is it that these dangerous bills came to exist in the first place?
First, and again, this is a critical battle to wage and win. SOPA is just the latest, but in many ways, the most absurd campaign in the endless saga of America’s copyright wars. It will be yet another failed attempt in a failed war, and I obviously believe it should be opposed.But second, and as you describe, this isn’t my war anymore. Not because my heart isn’t in it, but because I don’t believe we will win that war (or better, win the peace and move on) — even if we can win battles like this one — until the more basic corruption that is our government gets addressed. That’s the fight I have spent the last 4 years working on. That’s where I’ll be for at least the next 6.
For this is what I know: We will never (as in not ever) win the war you care about until we win the war against this corruption of our Republic.
Of course, as my book, Republic, Lost: How Money Corrupts Congress -- and a Plan to Stop It, describes, this is an insanely difficult, possibly impossible, fight. But whether difficult or not, it is the fight that must be waged.
We have done much. But in our celebratory enthusiasm, please take a moment to hear out Mr. Lessig, and appreciate just how far we have yet to go.
So yes, join us in fighting the obvious insanity of legislation like SOPA and PIPA that threaten the open, unfettered Internet. But please, please also join us in attacking the far more pernicious problem of lobbyist money subtly corrupting our government. If we don't deal with that, we will never stop fighting bills like SOPA and PIPA.
| [advertisement] What's your next career move? Stack Overflow Careers has the best job listings from great companies, whether you're looking for opportunities at a startup or Fortune 500. You can search our job listings or create a profile and let employers find you. |
GNU spotlight with Karl Berry (January 2012) [Recent blog posts]
In addition to the usual releases, a new installment of the Lilypond Report has been published. It includes release news, an interview, Prelude #1 in Scheme, and more.
To get announcements of most new GNU releases, subscribe to the info-gnu mailing list. Nearly all GNU software is available from ftp.gnu.org, or preferably one of its mirrors. You can use the URL ftpmirror.gnu.org/ to be automatically redirected to a (hopefully) nearby and up-to-date mirror.

Several GNU packages are looking for maintainers and other assistance. There's also a general page on how to help GNU, and information on how to submit new packages to GNU.
As always, please feel free to write to me, karl@gnu.org, with any GNUish questions or suggestions for future installments.
Generated by rawdog