Librenix
Headlines | Linux | Apps | Coding | BSD | Admin | News
Information for Linux System Administration 

E-book: Perl One-Liners Explained

Up
vote
Down

I'm happy to announce my 3rd e-book called "Perl One-Liners Explained."

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.

Here is an example. Suppose you quickly need to generate a random, 8 character password. You can do it quickly with this Perl one-liner:

perl -le 'print map { ("a".."z")[rand 26] } 1..8'

Overall, 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. read more...
mail this link | permapage | score:9283 | -pkrumins, February 4, 2012

Space Tyrant: A multiplayer network game for Linux

Up
vote
Down

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:

userndx=commscan(
tolower(
threc[th].inbuf
[threc[th].inptr][0]
),commlist
);
result=fp[userndx](th);

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.

makemap()
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.

command()
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.

jettison()
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.

warprtn()
jumprtn()
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:9250 | -Ray, May 30, 2005 (Updated: March 21, 2007)

Build Apps with Android SDK, Eclipse, PhoneGap (Ubuntu 10.10)

Up
vote
Down

This tutorial describes how you can set up a development environment for building Android apps on an Ubuntu 10.10 desktop using Eclipse, the Android SDK, and PhoneGap. I will describe how to build Android apps from the command line with PhoneGap and from the GUI with Eclipse and PhoneGap and how to test them in an Android emulator and on a real Android device. PhoneGap allows you to develop your Android applications using web technologies such as HTML, CSS, and JavaScript (e.g. with JavaScript libraries such as jQuery/jQTouch), and it will turn these web apps into native Android apps (in fact, PhoneGap supports multiple platforms such as Android, iPhone, Palm, Windows Mobile, Symbian, so you can use the same sources to create apps for multiple platforms). read more...
mail this link | permapage | score:9233 | -falko, January 27, 2011

Vim plugins: snipmate.vim

Up
vote
Down

This article introduces the snipmate vim plugin.

Snipmate.vim is probably the best snippets plugin for vim. A snippet is a piece of often-typed text or programming construct that you can insert into your document by using a trigger followed by a .

For example, you type "for" and press TAB, and the plugin inserts "for (i = 0; i < n; i++) { }" in your code! read more...
permapage | score:9201 | -pkrumins, August 10, 2009

Space Tyrant: A threaded game server project in C

Up
vote
Down

[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: A Space Tyrant has its own website! It's small but growing and will provide quick access to the latest code and developments in the ST universe.]

Space Tyrant: Today we kick off a new multithreaded, network socket programming project which we will call Space Tyrant. Our mission is to write an open source, multiplayer, networked, strategy game in the C programming language. The goal of this project is to make a solid code base which implements a simple space trading game upon which other games can then be built. The game will be a subset of The Last Resort (TLR) that currently runs at [offline]. This project will be a learning exercise for me as well as for any interested readers. The current state of the source code will be released with each article update.

The game design: While my TLR game consists of over 25,000 lines of C source code and supports a web interface as well as telnet and a graphical client, this code will be far smaller and simpler. It will initially only support telnet and will implement a far simpler game design.

Players will be able to telnet into the game, create an account, and play in a universe that contains ports, planets, as well as other players. Each player will be issued a starship, some cargo holds, and an amount of starship fuel. Additional fuel will be issued hourly and will accumulate in the starship. Fuel will be used to move the ship between sectors -- locations within the game universe -- and to dock with ports. Once a ship runs out of fuel it can't move at all until new fuel is issued.

Players will be able to buy and sell commodities (Iron, alcohol, and hardware) between the three different kinds of ports. Each port type will sell one of the three commodities and buy the other two. Prices will be based on supply and demand with rarely-used ports offering the better prices.

With the money players earn trading they will be able to buy more cargo holds to make their ships more efficient for trading. They will also be able to buy fighters -- small military drones -- that can be used to attack other ships or deployed to guard a sector and its contents. The fighters carried with a ship will guard it against attacks from other players.

Games will run for a predetermined length of time, then reset and start anew.

The programming model: Now, on to the software design. I've compared and considered various models for the server design. TLR is based on the forking model using inetd or xinetd to handle the listening and forking. While the forking model is inherently distributable to multiple processors, it introduces inefficiencies (forking multiple processes) and makes interprocess communications more difficult and slower.

Next, I considered a non-blocking, single process model. In this approach, one process handles everything in a single thread. It would use non-blocking IO (read and write functions that never wait for completion but, rather, return immediately if they aren't ready to read or write actual data). The thttpd web server is an example of a non-blocking, single process server. It's extremely fast and efficient. However, this model is quite complicated to code, and, I believe would make it more likely to introduce subtle timing bugs.

Next, I considered a pure multithreaded, single process model with a thread for each player. While appealing in many ways, this model would require the same kind of coordination between threads that the forking model requires between processes. Such interprocess communication would be simplified in that the various threads share memory, but the coordination issues otherwise remain the same.

Last, I considered another multithreaded model, this time with only IO threads for each user and a single thread that implements all game logic. While that one central thread might someday be a bottleneck that limits scalability on large SMP systems, it does distribute the IO on any additional processors that might be present, and requires minimal coordination. In short, this model combines the logic simplicity of the non-blocking single process model with the coding simplicity of the threaded model, while separating the IO from the main logic. There will also be two other simple threads in this model. There will be a thread that listens for new connections and spawns the IO threads for each new connection. There will also be a thread that writes the data to disk periodically.

This is the approach that I intend to take for this project. The code will be written for both Linux and Mac OS X.

More info: I have set up an email address for programmers following this series to provide recommendations, bug reports, and other feedback. Send email about this project to spacetyrant [at] librenix.com.
mail this link | permapage | score:9201 | -Ray, March 18, 2005 (Updated: July 26, 2008)

Tutorial: UDP socket based client server C programs

Up
vote
Down

This short and sweet tutorial has the example C source code for both a UDP client and server.
This article explains how to write a simple UDP client/server system in C for the Linux or Unix platform. Writing client-server applications using UDP sockets is considered very easy, yet we sometimes miss some essential steps, which results in spending more time in intense debugging sessions. I went through one such experience. It is quite hard to remember all the socket API details quickly without having to wade through tons of man pages, so this page lists the standard code for UDP Client Server program. I hope it will be useful for others, too.
[The original article has gone offline and the link has been replaced by a working page. -Ed.] read more...
mail this link | permapage | score:9186 | -Ray, February 23, 2004 (Updated: August 24, 2008)

Space Tyrant: Multithreading lessons learned on SMP hardware

Up
vote
Down

There is much to report in this update of Space Tyrant. Before getting into the new features and functions, I’ll dispense with the crisis of The Bug.

For a couple of weeks, we had been noticing odd anomalies with Space Tyrant (ST) running on the virtual server at Ioresort.com (now offline -Ed.). We never saw the problem on any other box -- and it was tested on at least four other Linux boxes and a Mac OS X system. We did all manner of stress testing, locally and over the Internet, script based and even feeding the game the output of /dev/random. Nothing caused the anomaly on any other box.

At first, I suspected that it might just be an obscure problem with the virtual server itself; after all, I had been forced to modify the TLR code to get it to run properly there. That problem turned out to be merely a limitation of NFS, not a bug with the virtual server software. However, the environment was clearly different from any other system I had used which raised my suspicions -- and reduced my urgency about looking for the bug.

While the bug wasn’t frequent, it was persistent. The bug appeared to be related to corrupted buffers or corrupted buffer indexes. Out of idle curiosity, I lowered the number of buffers used by ST to see if that affected the bug. Somewhat counter-intuitively, it substantially raised the frequency of the problem.

Brian Estabrooks (the hero of this release) and I spent more and more of our efforts hunting this incredibly elusive bug until that was all we were doing. I implemented various diagnostic routines hunting for clues. The all seemed to point to buffer indexes being changed incorrectly. Both Brian and I audited the code. It seemed impossible for the indexes to be changed improperly. Brian even went so far as to replace the ring buffer scheme with a high watermark approach but to no avail.

While I continued to suspect it to be a simple logic error in the code, Brian turned his efforts elsewhere. What he came up with was quite interesting. It seems that on many hardware architectures (most? all?), modifying a bit field can temporarily modify other bit fields in the same word! Now, this isn’t a problem on a single-CPU system; it repairs the damage in the same operation, making it, effectively, atomic. On an SMP machine, however, two different CPU’s working on different bit fields of the same word simultaneously create havoc. The operation isn’t really atomic and it doesn’t work.

Did I mention that the virtual server is a 4-way Xeon system?

The ring buffer indexing in ST relies on unsigned integer bit fields to automate wrapping back around to the first buffer after using the last one. My parsimonious programming, of course, packed all the bit fields together, several to a word. Brian’s test version of ST added a pad after each buffer index to round it out so that each bit field lived alone in its own complete word. We abused the new version for nearly an hour before either of us would dare say it. The bug was gone.

Yay!

So, the moral of this story is: Operations on sub-word fields affect other bits in that word (at least on many hardware architectures). Tread very carefully if multiple threads are accessing different bits in shared words. It may appear to work perfectly, only to crumble into a pile of smoldering rubble the first time it's loaded on a multiple CPU system!

Other than the primary lesson, some other good things came out of (the search for) the bug. Several other latent bugs were found and fixed and Brian and I are both much more intimate with the code.

And, on to the enhancements. ST is starting to look like an actual playable game. The following functions implement the new major features.

players(): We now have player rankings. It works by adding all the players’ ship resources to an integer array. Then it scans the universe looking for deployed fighters and adds those to the array as well. Currently, those two items comprise the total strength of a player.

It then sorts the array with a recursive bit-plane sort that I wrote for Starship Traders in 1998. The qsort() function in the C library was plenty fast, but took too much memory for my taste. Memory was a bit scarcer in those days and, worse, the SST software model gave each player his own copy of the server.

The sort reorders the array in place as follows. It scans the high-order bit in each element of the array. It then moves all elements starting with ‘1’ bits to the top and all starting with ‘0’ bits to the bottom. Next, it calls itself twice to reorder the first and second chunks of the array on the second bit. Each of those two instances of the sort then call the sort twice again, now giving 4 new sorts for the third bit, and so on. When all 32 bits are accounted for, the array is in the correct order with the top player on top, etc.

Scanning the entire universe can be expensive with a large map. Therefore, the player rankings function keeps the result and time stamps it. If another player asks for a player ranking within five seconds, the system just gives them the old one. After five seconds, however, any new request triggers a fresh listing.

autopilot(): We’ve added an autopilot to let a player find a specific sector -- or to locate the nearest planet. If you type a ‘0’ (zero), you’ll be prompted for a sector number within 1000 of the sector you’re currently in. You then will have the option of pressing ‘/’ to automatically warp to the destination sector.

If you’re looking for a planet, type the ‘L’ command that you would normally use to land on a planet in your sector. In the absence of a planet, the L key will engage the autopilot which will search for the nearest planet and give you a ‘/’ command to autowarp to it.

The new autopilot function consists of two other functions in addition to autopilot(), which is merely a control function. I had intended to use the old shortest path algorithm function from TLR but it was big and complicated. I decided to try to write a simpler, recursive shortest path algorithm instead. The new recursive function is much simpler but not quite as efficient as the giant for loop in TLR.

The actual algorithm is implemented in two functions called pathdepth() and pathcalc(). The pathdepth() function repeatedly calls pathcalc() with an increasing ‘depth’ parameter. ‘Depth’ tells pathcalc() how many levels deep to search before giving up.

The pathcalc() function simply looks to see if the sector it is looking at is the target sector. If not, it calls itself for each new sector that the current sector connects to. If the current sector is the target sector, it starts filling in an array for the autowarp() function to follow to reach the target sector. As the previous recursive calls to the pathcalc() function exit, they fill in the remainder of the path array.

And, yes, I seem to like reinventing the wheel. ;-)

The other interesting addition to the code is the backup thread. It is implemented by a function called backupdata() and works as follows: It scans the player data, the map data, and the history data looking for ‘dirty’ flags. (Whenever any persistent data is changed anywhere in the game, a dirty flag is set to tell the backup thread to write it out to disk.) This process is quite fast for a small game, but for a game with millions of sectors, it’s a significant waste of resources to scan the dirty flag array frequently.

Therefore, for the map and history data, I’ve implemented a ‘dirty block’ scheme as well. When a dirty flag is set, its corresponding dirty block flag is set too. Then, the backup thread need only scan the dirty block arrays, typically only about one percent the size of the arrays it represents. When a dirty block is found, only the hundred or so records it points to are scanned to find the actual dirty records for backup.

The backup file, named ‘st.9999.dat’ -- where ‘9999’ varies with the port number you run the game on -- goes into the current working directory from where you start the daemon. If the file doesn’t exist, a new game is started. Also, if you’ve modified the game in a way that changes the size of the data -- by increasing the map size, for example -- it will start a new game upon startup.

The game can be shut down from the command line by sending a signal 15 (kill -15 pid) or by the admin with the ^ command. Note that the first player to create an account in a new game automatically becomes the admin of the game!

makehistory(): The storing of historical data is new as well. Whenever another player attacks your ship while you’re logged off, you’ll get a report of the action and any losses when you next log on. Also, for remote deployed fighters, you never get immediate notification, so that information is stored in the history log even if you're logged on when it happens. You can view any accumulated event information since your login time by pressing the ‘e’ key.

deploy(): This simple function allows a player to deploy, or retrieve, guard fighters in a sector. Those fighters will not let another player pass through or view any of the contents of that sector. Any ships parked under the fighters are automatically protected against all attacks except for an attack by the fighters’ owner. Once the fighters are destroyed, of course, all ships there are visible and can be attacked.

There is also a newly implemented time limit in the game to limit the total online time of a day’s sessions to 4 hours. Like most other parameters, it can be changed by modifying a #define statement near the top of the code.

command(): The help page, a menu of available commands that a player can perform, has been redesigned and rewritten. This menu is attached to the '?' key.

The old debugger thread is gone, replaced by an in-game command function called showdata(). Press the ‘z’ key to see information on buffers, buffer indexes, and the backup thread’s state and history. Only if you’re serious about modifying the code will this information be useful.

The section of the gameloop thread that broadcasts radio and news messages has been modified to show only one of each type of message per pass. That way, replaying a long radio history won’t flood the output buffers and longer radio and news histories can therefore be retained.

The old jumprtn() movement function has been consolidated into the warprtn() function. It’s only slightly more complicated than having them separate.

The current source code can be downloaded from http://librenix.com/st/st.158.c. and the original article in this series is here. As usual, the compile script is embedded in the comments at the top of the source file. You’ll have to rename the source st.c for the script to work unchanged.

[A Space Tyrant home page has been created as a central index to the various ST articles, links, and files.]
mail this link | permapage | score:9155 | -Ray, June 26, 2005 (Updated: July 26, 2008)

Import XML into OpenOffice Calc with XSLT

Up
vote
Down

When it comes to importing generic XML into OpenOffice, the user is on his own. This article offers a quick XSLT tool for this purpose and demonstrates the Calc import of records-oriented XML. In addition to learning a practical trick for working with Calc, you might also learn a few handy XSLT techniques for using dynamic criteria to transform XML.
The popular open source office suite OpenOffice.org is XML-savvy at its core. It uses XML in its file formats and offers several XML-processing plug-ins, so you might expect it to have nice tools built in for importing XML data. Unfortunately, things are not so simple, and a bit of work is required to manipulate general XML into delimited text format in order to import the data into its spreadsheet component, Calc.
read more...
mail this link | permapage | score:9087 | -solrac, April 4, 2005

String matching in regular expressions

Up
vote
Down

Use parentheses to create the string matches you need in regular expressions. Parentheses allows you to use pipes for multiple matches. read more...
permapage | score:9085 | -aweber, September 12, 2011

Tutorial: Android development environment on Fedora 14

Up
vote
Down

This tutorial describes how you can set up a development environment for building Android apps on a Fedora 14 desktop using Eclipse, the Android SDK, and PhoneGap. I will describe how to build Android apps from the command line with PhoneGap and from the GUI with Eclipse and PhoneGap and how to test them in an Android emulator and on a real Android device. PhoneGap allows you to develop your Android applications using web technologies such as HTML, CSS, and JavaScript (e.g. with JavaScript libraries such as jQuery/jQTouch), and it will turn these web apps into native Android apps (in fact, PhoneGap supports multiple platforms such as Android, iPhone, Palm, Windows Mobile, Symbian, so you can use the same sources to create apps for multiple platforms). read more...
mail this link | permapage | score:9077 | -falko, February 1, 2011

Space Tyrant: A threaded C game project: First Code

Up
vote
Down

First code: This is the first code release of Space Tyrant. This is an early stage of development and, at this point, only implements the listening thread, the two IO threads for each player connection, and a skeletal game logic thread that does little beyond proof-of-concept code.

The design of the code was discussed in this article so you should probably go back and read that article if this is your first brush with this project.

The first code release -- what we will be discussing in this article -- is online as spacetyrant1.c. Download it as well as the shell script you’ll need to compile it: makeit1.sh. The script should work under both Linux and Mac OS X. The code will require a single line change to compile under Mac OS X. Search the code for the string OSX to find the line to decomment and the corresponding line to comment out.

Currently, the program allows multiple people to connect using telnet and echos anything they type to all other connected sessions. Some familiarity with the C programming language will be assumed in this article and those to follow.

Configuration constants: There are several ‘configuration constants’ defined by #define statements. The key constants and their meanings are:

MAXTH: This number represents the maximum number of users that can connect simultaneously. This constant is used to set limits on loops and to define the number of elements in various arrays. This number must be a power of 2.

MAXTHBITS: This is simply the number of bits necessary to form an unsigned int to index into arrays of MAXTH size. This number is used to declare bit fields for use with various items that occur MAXTH times. In the code we use a MAXTH of 256 and since 2^8 equals 256, MAXTHBITS is set to 8. Note that if you change MAXTH, you must make an appropriate change to MAXTHBITS!

MAXBUF: This is the number of buffers used in various places. For example, the input threads each get MAXBUF numbers of buffers.

MAXBUFBITS: This number matches MAXBUF in that it is the number of bits necessary to express the number MAXBUF in the same way that MAXTHBITS relates to MAXTH.

MAXLINE: This is the maximum length (in bytes) that is allowed for network input and output. The IO buffers, for example, are declared to be size MAXLINE + 1. The ‘+ 1’ is to allow room for a terminating 0.

RADPAD: This is added to MAXLINE to determine the length of a radio buffer. Radio buffers need to be larger than IO buffers since they must allow room for headers.

Data structures: Next, we declare a struct to contain most of the data associated with each thread. Note that this struct contains no player-specific data; it is used only to contain the data necessary to define an input thread and an output thread used to define one user connection. ‘threc’, as we will call the struct, will be an array with MAXTH elements. It will contain the thread ID of both the input and output threads, the timestamp of the last input from the input thread, the number of the socket descriptor, and various flags and indexes that will be used to coordinate the activities of the input, output, and game logic threads. Look at the code comments themselves for details on the variables.

Note that MAXBUFBITS is used to declare the size of inndx, outndx, inptr, and outptr. These variables, when incremented past the number of buffers, wrap back to zero, making it easy to implement ring buffers. That is why the MAXBUF number must be a power of 2.

The thread functions: In this program main() has two primary functions. First, it calls any initialization functions and clears the various data structures and spawns any other permanent threads. Second, it goes into an endless loop of accepting user connections and spawning IO threads to handle the newly connected users.

The next thread function, gameloop(), has the hard job. It constantly loops though the input buffers, looks for input that needs to be processed, and does it. While looping around the buffers, it also looks for input threads that have gone idle and terminates (‘reaps’) them. Currently, the only input processing it does to call a function named broadcast() with any data it finds in the input buffers. The broadcast() function simply copies the input to output buffers. This bit of processing is for proof-of-concept purposes only and will be replaced by actual game logic as it is developed.

The last important thread functions, userin() and userout(), exist in multiple pairs to perform network input and output duties for each connected user. The userin() thread reads the network connection and loads data into the next available input buffer (‘inbuf’). It then timestamps it, and goes back to waiting for more input. The userout() thread loops continously waiting for anything to appear in the next output buffer (‘outbuf’). When new data is placed in an output buffer by the gameloop() thread, userout() writes it to the user’s network socket.

Note that because userout() and gameloop() loop continously, they sleep after each ‘idle’ loop. That is, when they pass through their logic loop and find no actual work to do, they call the usleep() function to sleep a tiny fraction of a second. This sleeping prevents them from consuming unnecessary processor cycles.

[Update, June 25, 2005: A Space Tyrant home page has been created as a central index to the various ST articles, links, and files.]
mail this link | permapage | score:9039 | -Ray, March 27, 2005 (Updated: June 25, 2005)

The Real Microsoft Monopoly

Up
vote
Down

The courts have ruled that Microsoft holds a monopoly position in Intel PC Operating Systems. Business users have long been aware of Microsoft's lock on office productivity applications that require them to use MS Office in order to remain compatible with their business partners and customers. And web-surfing users are now using Internet Explorer in a ratio of about 8:1 over alternative browsers.

But one aspect of Microsoft's monopoly is more fundamental than any of those; the investment in skill, experience, training, and tools of Windows software developers themselves.

Those programmers, who have logged many long sessions of coding for the Windows environments, and with their deep immersion in its assumptions, tools, and API's, represent millions of person-years of Microsoft assets.

For years it has been a difficult decision for a professional developer to choose an environment other than Windows. The scale of that market dwarfs its competitors and opens to developers many more specialty markets than any alternative platform. Further, the sheer size of the Windows installed base is seen as a hedge against market change. Windows is perceived as a platform that will be with us for a long time to come.

Because it can take years of effort to reach the highest levels of productivity in a complex development environment, Windows-specialized programmers have, through economic necessity, been unable to switch to a different platform. With a large majority of developers writing code for Windows, the continued dominance of Windows applications was also assured. The monopoly was elegantly self-perpetuating.

Many companies, failing to appreciate the depth of Microsoft's monopoly and its determination to defend it, squandered valuable resources probing Microsoft's markets for an opportunity. After several spectacular failures, it seemed nearly impossible for such a locked market to break free of this cycle.

It seemed impossible, that is, until recently. Windows is no longer leading the growth curve among operating systems. The near perfect seal at the margins of the monopoly, it turns out, is only effective against competitors with a requirement to make money.

While Microsoft once made the fending off of mighty IBM look easy, the Linux phenomenon presents a very different kind of challenge. It needs no profits, corporate partnerships, or investors in order to succeed. Linux depends only on hobbyists' passion for programming and their self-imposed standards of quality in their own work. Further, the Linux community seems to draw motivation from its dissatisfaction with the computing landscape that Microsoft has created.

This noncorporate juggernaut has grown so large that it is spilling into commercial markets on many fronts. Now, with the additional support of several large corporations, the expansion rate of Linux could actually accelerate.

Much of the continued growth of Linux will come at the expense of Microsoft. Others will lose business along the way, of course, but the ubiquitous presense of Microsoft astride the market presents many targets that are simply too broad to miss.

Unfortunately for Windows programmers, at some point the rapid growth of Linux will force the saturated Windows market to start shrinking. Soon thereafter, the seller's market for Windows programming services will become a buyer's market -- and pay scales will begin to drop. Although the computer industry has experienced many of these disruptions in the past as new competition entered the market, this will be the largest such contraction by far.

Confidence in the impenetrable market lock of MS Windows is slowly fading. Some years from now when this trend reversal is complete and documented, we will look back to a single turning point to call the end of Windows' dominance. I'm making my pick a little prematurely. I think the critical point was IBM's decision to support and invest heavily in Linux.
mail this link | permapage | score:9016 | -Ray, July 9, 2001 (Updated: April 18, 2007)

Tutorial: MySQL Select statement

Up
vote
Down

An in-depth look at the syntax of the MySQL Select statement...
The SELECT statement is without question the most complex amongst MySQL’s data manipulation statements. Not surprising when you consider that the foremost purpose of structured query language (SQL) is to retrieve information from a relational database which adheres to a given criteria. Entire books have been written about how to construct a query to fetch the data that you’re after. That’s not the purpose of this article. Our goal will be to cover the syntax of the SELECT statement and gain an understanding of its many optional clauses. We’ll start at the beginning and work our way through them. When we’re done, you’ll understand which clauses to use for different purposes. We’ll leave the twenty table joins for another day.
read more...
mail this link | permapage | score:9010 | -Ray, August 31, 2010

Scripting: Put a clock in your bash terminal

Up
vote
Down

In the original version, the cursor positioning didn't work on my Mac OS X system. If that happens to you, try this simplified variant:
  #!/bin/bash
while true
do
tput sc
tput cup 0 60
echo -en `date +"%H:%M:%S %F"`
tput rc
sleep 1
done
Also, note that you'll need to run either script in the background to use your terminal.
The script saves the current cursor position with an ANSI escape sequence instruction. Then, using the tput command, the cursor is sent to row 0 (the top of the screen) and the last column minus 19 characters (19 is the length of HH:MM:SS YYYY-MM-DD). The formatted date command is displayed in green inverted color. The cursor is then sent back to its original position with another ANSI sequence that restores the original saved position.
read more...
mail this link | permapage | score:9002 | -Ray, January 22, 2008

Programming Language Tradeoffs: 3GL vs 4GL

Up
vote
Down

Level of Abstraction
The level of abstraction that a programming language provides is all about tradeoffs. Lower level languages (I'll inaccurately call them 3GL's) supply a few small operations which can be combined with great flexibility to accomplish almost anything. The cost, of course, is in the time-consuming detail in which each and every bit of code must be cast. Conversely, high level languages (loosely, 4GL's) and application generators include meta-operations which provide much more functionality for a given amount of code. Once again, there is a cost. Here the big penalty is a loss of flexibility -- which is proportional to the size of the functional units. There are a prohibitively large number of ways in which a few small operations can be combined to create large ones. Therefore, only the most common of these large functions can be reasonably implemented in a high level language before the point of diminishing returns is reached. As the language integrates more large functions into its syntax, its complexity eventually reaches a point where a high level of skill is required to use it effectively.

Special-purpose Libraries
The original distinction between 3GL and 4GL languages has long been blurred by the availability of prepackaged libraries. For example, there are a wide variety of special-purpose function and class libraries on the market for C and C++. These tools lets experienced programmers use their general-purpose language skills while adding only the specialized components needed to complete an application. The details of using the library follow the patterns that they already know, leaving them to learn only the minimum necessary to write their specialized program.

Applications Generators
Meanwhile, programming with some application generators no longer resembles traditional coding -- but the same type of decisions are being made and the same kind of work is being done. The units of functionality are larger, of course, and the methods of manipulating the chunks of logic are usually different as well. Only if the generator is a good match for the application, however, will the potential productivity advantage of this approach be fully achieved. In selecting such a tool, the same tradeoffs that apply to the choice of 4GL's versus 3GL's must be considered. Application generators don't represent a fundamental change in the nature of programming but rather just another point in the continuum of low and high-level programming.

Intermediate Code
To blur the distinction further, the ability of some 4GL's to generate 3GL intermediate code would seem to give the developer the best of both worlds. It retains the productivity of high-level programming and provides access to the machine efficiency and low-level flexibility of a 3GL -- just as the libraries for 3GL's seem to do. While this approach should result in an environment that is as flexible as the 3GL alone, it comes with a tradeoff. To exercise the flexibility of the 3GL it becomes necessary to program in two languages, which increases maintenance costs and training requirements.

The Right Tool for the Job Versus Expertise
Further complicating the issue is the matter of expertise. A very specialized language may be the most productive for a particular application. However, experts in a more generalized language might complete the application on schedule more predictably than would neophytes with a special-purpose language. Of course, the practitioners of the general-purpose language get more opportunities to hone their skills.

Because of this effect, choosing the best language for each particular application might not always be the optimum overall strategy.


[The author codes in C and PHP and no longer uses COBOL, Atari BASIC, Visual BASIC, FORTRAN, ALGOL, Natural, RPG, or IBM 370 Assembly.]
mail this link | permapage | score:8992 | -Ray, June 24, 2001 (Updated: November 29, 2002)

I wrote my first programming e-book: Awk One-Liners Explained

Up
vote
Down

I really love writing about programming and Linux, and I just published my first e-book ever on Awk one-liners.

Awk one-liners are short Awk programs that fit on one line and do one particular task, such as numbering lines, double spacing lines, printing only lines that match a pattern, etc.

Here is an example. The following one-liner prints all users on the Linux system:

awk -F: '{ print $1 }' /etc/passwd

This one-liner works this way. The -F: command line argument specifies that the lines in the /etc/passwd file should be split into fields by the colon character. As we all know, the information in /etc/passwd file is colon separated, so the first field $1 gets set to the username, the second field $2 gets set to the password, the third field $3 gets set to user id, etc. This one-liner prints only the first field which is the username. Simple, isn't it?

In my 50 page long e-book I carefully explain 70 one-liners in similar way.

Here is the table of contents of the e-book:

Preface.
1. Introduction to Awk One-Liners.
2. Line Spacing.
3. Numbering and Calculations.
4. Text Conversion and Substitution.
5. Selective Printing and Deleting of Certain Lines.
6. String and Array Creation.
Appendix A: Awk Special Variables.
Appendix B: Idiomatic Awk.
Index.
read more...
mail this link | permapage | score:8980 | -pkrumins, June 24, 2011

Introduction to Java programming

Up
vote
Down

This two-part tutorial introduces the structure, syntax, and programming paradigm of the Java language and platform. In Part 1, learn the essentials of object-oriented programming on the Java platform, including fundamental Java syntax and its use. In Part 2 explore the more-sophisticated syntax and libraries you will need to develop complex, real-world Java applications. read more...
mail this link | permapage | score:8953 | -solrac, August 24, 2010

Secure String Coding in C and C++

Up
vote
Down

This excerpt from the $35 book Secure Coding in C and C++, also covers common string manipulation errors.
Strings—such as command-line arguments, environment variables, and console input—are of special concern in secure programming because they comprise most of the data exchanged between an end user and a software system. Graphic and Web-based applications make extensive use of text input fields and, because of standards like XML, data exchanged between programs is increasingly in string form as well. As a result, weaknesses in string representation, string management, and string manipulation have led to a broad range of software vulnerabilities and exploits.
read more...
mail this link | permapage | score:8945 | -Ray, December 6, 2005

Eclipse: Use gdb from CDT

Up
vote
Down

The GNU Debugger (gdb) is the most popular open source debugger in use. Learn how the Eclipse C/C++ Development Tooling (CDT) talks to the GNU Debugger. This concrete example of CDT-debugger interaction should be helpful for anyone wishing to interface a custom C/C++ debugger from CDT. read more...
permapage | score:8930 | -jmalasko, July 4, 2008

Mono-culture and the .NETwork effect

Up
vote
Down

Consider a future where Microsoft has succeeded in migrating most Windows development to the .NET framework. With the considerable power that Microsoft wields over corporate desktop computing, the success of .NET is easy to foresee.

Now, imagine for a moment that Mono, following in .NET's footsteps, is also hugely successful. Further, imagine that, in its success, Mono displaces a large portion of traditional Linux software development over the next few years.

I believe that if the above scenario becomes reality it could lead to a disaster for Linux. In such a future, Microsoft would have tremendous leverage over Linux, Linux programmers, and businesses using Linux.

Microsoft can, at a carefully selected time, change key interfaces, sue for patent infringement, and release otherwise standard .NET components that break or obsolete pieces of Mono. They can also use the powers of the DMCA to prevent Mono developers from gaining access to obfuscated components of .NET technology. While hobbyists and Linux-centric companies will be able to withstand such inconveniences (with the possible exception of patent suits, of course), general businesses and organizations will not be able to resist such pressure.

Of course, Microsoft is well aware of how this scenario could unfold and has thought of many more exploitable details than a casual observer such as myself.

Mono, if successful, is a gift from heaven to Microsoft that, when the timing is right, can be used to set Linux deployment back years, or worse, depending on the devastating psychological and economic effects such a maneuver would have on Linux developers and businesses.

For Microsoft, their best strategy to do real damage to Linux is to make it easy for Mono to succeed while carefully laying their traps. They can quietly go about the business of patenting all of the key functions of .NET. Anyone who has followed the trend of software patents must realize that Microsoft could have dozens of patent claims covering .NET before Mono rises to prominence.

Then, Microsoft need only wait. The optimum time to shut down Mono will be after much Linux development has committed to it. By then, Mono technology will have infected many projects. Perhaps worse, it will be easier for Mono programmers to simply switch platforms and become Windows developers rather than learn alternative methods and tools of Linux development. Programmers have to eat and software development houses must pay the bills. In such a scenario, there is not a year to burn while everyone ramps up their skills with new tools and practices.

Meanwhile, businesses will be forced to abandon any Linux packages that are .NET-encumbered. Since a .NET version of each Mono-based program would already exist, it would take only a few such packages to convince a business to migrate off of Linux. The headaches of replacing such packages under Linux need only exceed the alternative headache of simply switching to Windows.

A company with their own custom Mono-based software would have fewer options. Microsoft, however, would likely provide an easy solution; simply move the Mono software to .NET and it will all be legal.

I am not the first person to have thought about this. Several Slashdot users have posted cautionary messages about developers placing their trust in the good intentions of Microsoft. [1, 2, 3, 4, and 5].

Dave Winer also seems to wonder about Microsoft's oddly open behavior:
The first clue should be that Microsoft is not protecting the source of .NET, in fact they're publishing it, with some constraints, but if you want to see how they do it, they say there will be no mysteries and no poison pills. So they're making it not impossible to clone. Why are they being so generous? (A little sarcasm, sorry.)
Even Miguel de Icaza1, the founder of the Mono project, acknowledges the compatibility hazards:
If Microsoft decided to make our life really hard in terms of compatibility, it would also hurt its own customers. If it changes the APIs, that affects its customers as well. So I think the APIs will remain fairly stable, and I hope that Microsoft won't go into proprietary protocols or protocols that would make it really hard for us to implement Mono. There's is always the possibility it will do so. Microsoft has some strange patterns in terms of how it competes. I really hope it will "behave like a good citizen," as Steve Ballmer said recently it would.
What I've described here is probably a worst-case scenario; in all likelihood Mono will not be so successful as to cause a large problem for Linux if and when Microsoft decides to kill it. However, even in a favorable sequence of events, Microsoft will still hold the power to cause a large amount of open source effort and code to be lost.

1. Miguel rebuts one of my points here.
mail this link | permapage | score:8924 | -Ray, October 13, 2003 (Updated: October 14, 2003)
More coding articles...
Buy Abstract Art Prints

Selected articles

Shadow.sh: A simple directory shadowing script for Linux

Scripting: A parallel Linux backup script

Download: Linux 3D Client for Starship Traders

Why Programmers are not Software Engineers

Space Tyrant: A threaded C game project: First Code

Apple DIY Repair

The Network Computer: An opportunity for Linux

Closed Source Linux Distribution Launched

VPS: Xen vs. OpenVZ

The Real Microsoft Monopoly

The short life and hard times of a Linux virus

No, RMS, Linux is not GNU/Linux

Programming Language Tradeoffs: 3GL vs 4GL

Testing the Digital Ocean $5 Cloud Servers with an MMORPG

How to install Ubuntu Linux on the decTOP SFF computer

Missing the point of the Mac Mini

The life cycle of a programmer

Beneficial Computer Viruses

Linux dominates Windows

Librenix T-Shirts and Coffee Mugs!

Space Tyrant: Multithreading lessons learned on SMP hardware

Microsoft to push unlicensed users to Linux

MiniLesson: An introduction to Linux in ten commands

Space Tyrant: A threaded game server project in C

The Supreme Court is wrong on Copyright Case

Space Tyrant: A multiplayer network game for Linux

Linux vs. Windows: Why Linux will win

Apple to Intel move no threat to Linux

Graffiti Server Download Page

Mono-culture and the .NETwork effect

Why software sucks

Tutorial: Introduction to Linux files

Hacker Haiku

 

Firefox sidebar

Site map

Site info

News feed

Features

Login
(to post)

Search

 
Articles are owned by their authors.   © 2000-2012 Ray Yeargin