Librenix T-Shirts and Coffee Mugs!
|For today's example of my (semi)elite C programming skilz, I submit for your inspection the Librenix T-Shirts! Yes, I created the images on these shirts and coffee mugs entirely with C code. While the code isn't up to the standards *cough* of my open source Space Tyrant project, at least the output is colorful and not entirely textual!|
click either image to see the T-Shirts, Coffee Mugs, etc.
(If you like the images but don't care for 'librenix' on your shirt, these same styles are available for all 50 US state names as well as with the signs of the zodiac here)
(and here are some modern prints)
|mail this link | permapage | score:9426 | -Ray, June 6, 2010 (Updated: May 13, 2014)|
How to install Ubuntu Linux on the decTOP SFF computer
I recently bought a decTOP small form factor (SFF) computer. My goal was to build a cheap, fanless, quiet, and low power consumption Linux server. For $99 plus the cheapest available shipping, $40, my machine arrived 11 days after I placed the order.
This is a tiny computer, about the size of a Mac Mini. But, because it has no fan, it runs a bit quieter and, with the help of a 1-watt, 366 MHz CPU, consumes only 8 watts. For comparison, the G4 Mac Mini consumes about 20-30 watts, depending on load.
The decTOP comes with 128 MB of RAM in its sole SO-DIMM slot and a 10 GB 3.5 inch hard drive. I understand that it's a simple matter to replace the drive and to upgrade the memory to a maximum of 512MB.
It also comes with no operating system and the ability to boot only from a USB drive. This article details the steps I used to build the USB boot/installation drive and install Ubuntu 6.06 on the decTOP.
There is another article -- with additional decTOP links -- here on installing Ubuntu 6.06 on the decTOP with the aid of a Windows system. Fortunately ;), I run Mac OS X and Linux (Ubuntu 7.04), so that article didn't work for me. I did the installation of the Ubuntu 6.06 LTS Server Edition using my Ubuntu Linux box and a 1 GB USB flash drive -- although a 512 MB USB drive should work as well.
- Download the Ubuntu 6.06 server ISO image from the Ubuntu download page. Depending on your plans for the decTOP, you might want to choose the desktop version. Unless you have already upgraded your decTOP's memory, however, you'll want to stick with the 6.06 releases.
- Install the mbr, mtools, and syslinux packages on the Linux system you'll be using to prepare the USB drive. If you run Ubuntu or some other Debian-derived system, the following commands may do the work for you.
apt-get install mbr
apt-get install mtools
apt-get install syslinux
- Partition the USB drive with a single FAT-16 partition. I used the fdisk 'n' command to make the new primary partition 1. The fdisk 't' command can be used to change the partition type to FAT-16. My device name was /dev/sda.
- Make the FAT-16 partition the active partition. I used the fdisk 'a' command.
- Install a master boot record on the USB drive.
- Install syslinux on the USB drive. Note that the USB drive should not be mounted when you do this.
syslinux -s /dev/sda1
- Create a mountpoint and mount the ubuntu ISO image using the loopback device.
mount -o loop -t iso9660 ubuntu.iso /iso
- Create a mountpoint and mount the USB flash drive.
mount /dev/sda1 /usb
- Copy the contents of the ISO image to the USB drive. This will take some time.
cp -r . /usb/
- Copy the /usb/dists/dapper directory into a new /usb/dists/stable directory.
cp -r dapper/* stable
- Copy several files from /usb/install to the /usb root directory.
cp /usb/install/vmlinuz /usb/
cp /usb/install/mt86plus /usb/
cp /usb/install/initrd.gz /usb/
- Install the following text into a file named syslinux.cfg in the /usb root directory.
append initrd=initrd.gz ramdisk_size=24000 root=/dev/ram rw
- Flush all writes, unmount, and remove the USB drive. After the sync step, wait for all of the data to be written to the USB drive.
- Connect the ethernet adapter to the decTOP and connect it to your network to allow automatic configuration of the network interface.
- Insert the USB drive into the decTOP and power it up. The decTOP should automatically boot from the USB drive and start the Ubuntu installation.
- Answer only the first two questions concerning language selection and go to the next step, below.
- Press Alt-F2 (hold down the Alt key and press the F2 function key) to open a shell. Then press enter to start the shell.
- Create a /cdrom and a /dev/cdroms directory in the installation ramdisk
mkdir /cdrom /dev/cdroms
- Go to the /dev/cdroms directory and build a symlink from /dev/sda1 (that is likely the device name of your USB boot partition) to /dev/cdroms/cdrom0.
ln -s ../sda1/cdrom0
- While still in the shell, mount the USB drive to mimic an installation CD-ROM.
mount -t vfat /dev/cdroms/cdrom0 /cdrom
- Return to the installation program with Alt-F1 and continue the installation.
From this point, the process should be identical to a routine CD-ROM installation.
For a grand total of $140 and 8 watts of power consumption, I now have a near-silent Linux server running 24/7. You can telnet to it here and marvel at its blinding speed running a 250,000-sector Space Tyrant game.
|mail this link | permapage | score:9383 | -Ray, August 16, 2007 (Updated: April 26, 2011)|
Tutorial: Introduction to Linux files
|This newbie-level Linux tutorial is an introduction to handling files from the Linux command line. It will cover finding files, determining their type, renaming, copying, examining their attributes, reading their contents, and, in the case of binary files, how to get clues to learn something more about them. Further reading will be suggested for editing files since that topic is beyond the scope of this article. |
The reader of this tutorial is expected to have access to a Linux system and to perform the example commands as we progress through the tutorial. Once logged in to your Linux system, open a terminal session. Under Red Hat Linux, terminal is found in the 'system tools' section of the menu. (Your system may, alternatively, use a terminal program called 'konsole', 'xterm', or 'shell'. Look around your system for a menu with 'tools' or 'utilities' in the name if necessary.)
ls: Listing files
Let's start with the ls command. ls is an abbreviation for list files. Type ls now, then press the 'enter' key to see the names of the files in your current directory. The results from my 'tmp' directory are listed in bold below:
$ ls /tmpNote that I said 'your current directory'. To get the a listing of files in another directory, enter ls [dir] where [dir] is the name of the directory you wish to look at. For example, to see the file names in your top level directory, '/', type the following:
$ ls /For more information on the files, use one or more of the ls command line switches. Here I use ls with the -l switch for a 'long' listing:
bin dev home mnt
proc sbin tmp var boot etc
initrd lib opt root sys usr
$ ls -lNote that with the -l switch we get the file permissions, the inode links, the owner and group names, the file size in bytes, and the timestamp of the file as well in addition to the name. The ls command has many more options. Type man ls for a full list of options.
-rw-r--r-- 1 root root 9649
Mar 28 02:47 tardir.0.log
file: What is this file?
Linux also provides a handy command to help determine what type of files you are dealing with:
$ file tardir.0.logThe Linux (and Unix) file command knows about, and can detect, many different file types. In our example, file tells us that tardir.0.log is a simple ASCII text file.
tardir.0.log: ASCII text
less: Paging through a file
Now, to actually look at the contents of a text file, we have many options. The most common is the more command and a more elaborate, newer command is less. I like less because it lets you use the arrow keys for scrolling and the pgup/pgdn keys for paging through the file. The following is a condensed page from the command less tardir.0.log:
home/tfr/From the ':' prompt we can page or scroll forward or backward. We can also type /star to search for the next occurrance of the string 'star'. Enter man more or man less for more information on the more or less commands, respectively.
[ . . . ]
mv: Renaming a file
Now, suppose we want to rename a file. Under Linux (and Unix) we 'move' it with the mv command as follows:
$ lsNote that the mv command only produces output when there is an error. In this case, we encountered no error so mv quietly performed its work.
$ mv tardir.0.log tar.log
cp: Copying files
To make an actual copy of a file, we use the cp command. For example, to make a backup copy of tar.log named tar.log.2, we enter the following:
$ cp tar.log tar.log.2Again, we get no output to the screen when the cp command is used without error. We had to use the ls command to see the result of the command. Enter man cp for more details of the cp command.
strings: Looking for text in a binary file
Now, to actually look inside an unknown binary file for text strings there is a command called, appropriately enough, strings. For example, if we run the strings command on the 'echo' program, we get, in part, the following:
$ strings /bin/echoType man strings for more information.
Copyright (C) 2004 Free
Software Foundation, Inc.
Written by %s, %s, %s,
%s, %s, %s, %s,
%s, %s, and others.
grep: Finding particular strings in a file
To look for a particular text string in a file, we use the grep command:
$ grep html tar.logAnd, of course, man grep will retrieve additional instructions for the grep command.
find: Finding files by name
To find all files with a particular name on your system, use the find command. For example, to find files named 'echo', enter the following:
$ find / -name 'echo'Further, to find all files in the /var filesystem with the string 'echo' in their names, enter this:
$ find /var -name '*echo*'
To get started editing text files try this tiny vi tutorial. After going through the quick tutorial, you can click the contents button and reach an advanced vi tutorial as well as other vi information.
For information on moving around in a Linux filesystem try this Introduction to Linux in ten commands. That article also provides additional examples on some of the commands covered here.
|mail this link | permapage | score:9367 | -Ray, April 2, 2005|
Space Tyrant: A multiplayer network game for Linux
|Since the last release of Space Tyrant, it has gained some actual game-like functionality. The new code can be downloaded from st2.c. Download it as well as the shell script you’ll need to compile it: makeit2.sh.|
It’s now possible to connect to the game via telnet and to create an account, log in, and be issued a ship. Once you’re logged in, there is a universe to explore filled with ports for buying and selling goods and planets for scooping free goods. From those trading activities you can earn money, called microbots. Other than trading to earn more money, you only use your microbots to buy fighters -- which you can use to attack other players or the neutral fighters that guard some sectors.
The neutral fighters are only good for parking under while you’re not playing. They afford a little bit of free protection for your ship since no one can attack you until they first destroy the neutral fighters. Note that you can attack other players whether they are logged in or not and any fighters with their ship will automatically try to defend them.
Each player starts out with a specific supply of fuel, called antimatter. Each minute a small amount of additional antimatter is issued by a function called updatefuel(). If you’re not logged in, fuel just accumulates in your ship. This continuous allocation of fuel makes Space Tyrant a type of turn-based game. Unlike traditional turn-based games, however, you can play your fuel all at once or a little at a time and completely independently of how and when other players play.
You can also talk to other players on the radio. There is only one channel so everyone who is logged in hears everything that is said on the radio.
The game isn’t yet playable in any reliable sense, however, because it doesn’t yet back up and reload the data from disk files. The software creates an instance of the game when you run it and it remains running until you stop it or the system goes down. There is also no way to establish a time limit on a game.
That’s pretty much the extent of the functionality changes. Now, on to the code.
First, there is a login function. That function looks in the player database struct and, if the player name doesn’t already exist, it creates an account there. If the name does exist, it prompts for a password, matches it against the stored password, and logs you in if the two match. There is not yet a way to change your password.
Once a player is logged in, he is faced with a sector description and a ‘choice:’ prompt. Any character that the player types at this prompt is immediately acted on as if it were a command. There is a string called ‘commlist’, short for command list, containing the letters and characters that are used as commands. A function pointer array, ‘fp()’, is used to store the locations of the command functions. Another function called ‘commscan()’ looks up the command letter typed and returns an index into the fp() function pointer array. This combination of the commlist string, the commscan function, and the fp function pointer array constitute the command processing loop of the game, as shown below:
These lines are embedded in a loop where each user’s input thread, represented by the variable ‘th’, is examined for new input. The new input arrives in string called inbuf. Since each thread has several buffers, an index called inptr is used to keep track of which one is currently being processed.
And, as described above, commscan is used to extract the appropriate function index and place it in a variable called ‘userndx’. Then, userndx is used to index into the fp function pointer array and the thread index (th) is passed to the appropriate command-processing function.
There’s a small amount of misdirection in that first line but, once understood, it becomes trivial to add additional commands. Basically, you just need to replace the placeholder function, ‘nullrtn’, with your new function name adjacent to the command letter you select in the fp() definition list.
The new functions are discussed below.
In keeping with the evolving game nature of this project, several actual game functions have been added. The first new function, makemap(), builds a 20,000-sector single-galaxy universe and populates it with objects. By changing the GAMESIZE constant, you can build a universe of arbitrary size, but make sure you don’t try to build a universe so big as to consume too much of your system’s memory. I’ve tested universes of up to 1,000,000 sectors, which seem to work just fine. The makemap() function randomly puts ports, planets, fleets of neutral fighters, and nebulas in various sectors throughout the universe, and interconnects the sectors with randomly-generated one-way ‘warps’. Note that planets and ports are randomly given varying productivity's and random initial inventories of our three commodities: Iron, Alcohol, and Hardware.
Note that makemap() builds each sectors array of six warps, sorts them into ascending order, and then looks for duplicate warps. If any duplicates are found, it decrements the loop-controlling variable and simply rebuilds that entire sector from scratch. The sorted warps are a convention that we will maintain throughout the project. Each new galaxy type that we add in the future will adhere to that convention and other functions (and users) will be allowed to assume that warps are in ascending order.
We have added a function to simply list the implemented commands and a short line of description. For now, the function is attached to the command letters ‘?’ and ‘H’ via the function pointer array and the commlist array. This function is mostly useful to illustrate a design limitation. The output of any single sprintf buffer-building function cannot exceed the MAXLINE buffer size constant. This function produces a single buffer out output very near the current 511-byte limit and will soon have to be split to produce two buffers of output. Assuming, of course, that we don’t increase the MAXLINE buffer size.
The ‘J’ command activates the jettison() function. It’s only purpose is to dump any cargo out of your cargo holds. It illustrates the method we use to let a function that requires multiple characters of input -- or simple confirmation -- to temporarily turn off command processing and send the next character of input back to it. Jettison requires confirmation so that you don’t accidentally dump your cargo just by hitting the J key. (Since all commands operate as ‘hot’ keys you do not have to hit the [Enter] key to activate a command -- each command immediately executes as soon as you press a key.)
Each command function has the ability to set the thread’s control variable to it’s own command letter. That way, the command processing loop can simply check ‘control’ pass the next buffer of input directly to whichever function is indicated.
The warprtn and jumprtn functions process requests to move to another sector. warprtn() processes the commands 1, 2, 3, 4, 5, and 6, which represent a user’s request to move to the first through the sixth sector number in the warp list, respectively. jumprtn() processes requests to move to a randomly selected sector in the warp list via the ‘-’ (or ‘=’) key. jumprtn() also implements commands to move to the next larger sector, the next smaller sector, as well as the largest and smallest sector number via the ‘.’, ‘,’, ‘>’, and ‘game design and the programming model. The second article discusses the IO handling code and more of the details of the programming model.]
[Update, June 25, 2005: A Space Tyrant home page has been created as a central index to the various ST articles, links, and files.]
[Update, March 21, 2007: Space Tyrant now has a website of its own!. This site is new but growing and will be the quickest way to find new information and code on the Space Tyrant project.]
|mail this link | permapage | score:9289 | -Ray, May 30, 2005 (Updated: March 21, 2007)||