For projects 8 and 9, we need to get input for 6 employees and return a formatted list for a payroll sheet.
In pseudo code (not actual code), this goes something like:
Create a temp file containing the headings (number, name, rate, hours, etc)
(echo "Number Name Rate...etc" > temp)
Create a total variable to store overall total pay for all employees
While loop for 6 passes
read number name rate hours overtime
regularpay=rate*hours
overtimepay=rate*overtime
totalweeklypay=regularpay+overtimepay
total=total+totalweeklypay
store variables as a new line in temp file
(number name rate hours overtime regularpay overtimepay totalweeklypay >> temp)
done with while loop
echo “Weekly Payroll”
use awk to format each line from the temp file awk '{printf "%-6s%-13s%-10s%5s%8s%10s%9s%8s%8s\n", $1, $2, $3,"$"$4, $5, "$"$6, "$"$7, "$"$8, “$”9}' (you may need to edit the %numbers)
echo “Total: \$$total”
Also, to make this work for reading from a file for project A, try adding “< $1” after the “done” in the while loop. This takes the first parameter passed at the command line and uses it as the file entry for the read command.
That gets you through project B, actually, since the AWK command is all that’s needed to complete it. As for “discount”, that’s a new script, and can be found entirely in the student manual, under page 34 or 35 I believe.
Good luck, acolytes!
A mess of a blog, just like my mind. A little bit of everything, scattered about, and rarely updated.
Tuesday, December 6, 2011
Monday, December 5, 2011
Ways with Arrays
A collection of variables can be stored within one variable using an array. It's fairly straghtforward; simply call like a variable like normal, but add a number after it with [] brackets, like this: variable[1]
This one's going to be a hefty example, so bear with me.
#!/bin/bash
#
#Array Demo
#By Jason Groce
#Created 12/5/2011
#
#An Array is a variable that contains multiple values.
#Each value is numbered after the name of the array,
#such as array[4], which may be used as a standard
#variable with special notation, such as $(array[12])
#
echo "This is a demo of how an Array functions."
echo -ne "You may pass a file name to populate the array "
echo "or enter variables manually."
echo -ne "(The file should contain names and numbers,"
echo "one of each per line.)"
echo
typeset -a names
typeset -a numbers
typeset -i num=0
if [ ! -f $1 ]||[ ! $# -eq 1 ] #if no filename entered
then
echo -ne "You did not enter a valid file name; "
echo "begin manual entry."
echo "Please enter 10 Names, one per line: "
num=0
while [ $num -lt 10 ] #10 times, save name to record
do
read names[$num]
num=$num+1
done
echo "Please enter 10 Numbers, one per line: "
num=0
while [ $num -lt 10 ] #10 times, save number to record
do
read numbers[$num]
num=$num+1
done
else #if a valid file name entered as parameter
echo "You entered file $1"
num=0
echo "Populating arrays..."
while read name number #record name/number for each line
do
names[$num]=$name
numbers[$num]=$number
num=$num+1
done < $1
fi
num=$num-1
typeset -i record=0
while [ ! $record -eq 99 ]
do
echo -ne "Enter a number 0 to $num to display a record "
"or '99' to quit: "
read record
case $record in
99) echo "Quit"
exit
;;
*) typeset -i recordNum=$record
echo -ne "Record $record "
echo -ne "${names[$recordNum]} "
echo "${numbers[$record]}"
esac
done
This script can be coupled with a file containing names and numbers/values, such as this:
Paul pbille
Jason f52560
Richard f49150
Jonathan f51970
To try this out, creating the script as "arrays.sh" and the file as "arraydata.dat", run the command like this:
./arrays.sh arradata.dat
To summarize this, you create an array with typeset -a variable, add data to each array value like this, variable[5]="data", and access that data like this, ${variable[5]}.
Questions? Enjoy, weenix's!
This one's going to be a hefty example, so bear with me.
#!/bin/bash
#
#Array Demo
#By Jason Groce
#Created 12/5/2011
#
#An Array is a variable that contains multiple values.
#Each value is numbered after the name of the array,
#such as array[4], which may be used as a standard
#variable with special notation, such as $(array[12])
#
echo "This is a demo of how an Array functions."
echo -ne "You may pass a file name to populate the array "
echo "or enter variables manually."
echo -ne "(The file should contain names and numbers,"
echo "one of each per line.)"
echo
typeset -a names
typeset -a numbers
typeset -i num=0
if [ ! -f $1 ]||[ ! $# -eq 1 ] #if no filename entered
then
echo -ne "You did not enter a valid file name; "
echo "begin manual entry."
echo "Please enter 10 Names, one per line: "
num=0
while [ $num -lt 10 ] #10 times, save name to record
do
read names[$num]
num=$num+1
done
echo "Please enter 10 Numbers, one per line: "
num=0
while [ $num -lt 10 ] #10 times, save number to record
do
read numbers[$num]
num=$num+1
done
else #if a valid file name entered as parameter
echo "You entered file $1"
num=0
echo "Populating arrays..."
while read name number #record name/number for each line
do
names[$num]=$name
numbers[$num]=$number
num=$num+1
done < $1
fi
num=$num-1
typeset -i record=0
while [ ! $record -eq 99 ]
do
echo -ne "Enter a number 0 to $num to display a record "
"or '99' to quit: "
read record
case $record in
99) echo "Quit"
exit
;;
*) typeset -i recordNum=$record
echo -ne "Record $record "
echo -ne "${names[$recordNum]} "
echo "${numbers[$record]}"
esac
done
This script can be coupled with a file containing names and numbers/values, such as this:
Paul pbille
Jason f52560
Richard f49150
Jonathan f51970
To try this out, creating the script as "arrays.sh" and the file as "arraydata.dat", run the command like this:
./arrays.sh arradata.dat
To summarize this, you create an array with typeset -a variable, add data to each array value like this, variable[5]="data", and access that data like this, ${variable[5]}.
Questions? Enjoy, weenix's!
Wednesday, November 30, 2011
Passing the Parameters, Please!
When entering a command to run a shell, you can actually tell the program information on
the same line. These parameters can be used within the script as variables. For
example:
$> ./program.sh Jason 50 75
This tells the program to use Jason as the first parameter, 50 as the second, and 75 as
the third. In program.sh, we can access the parameters like this:
echo "Name: $1"
echo "One: $2"
echo "Two: $3"
The $ sign followed by a number is special in unix scripting to use parameters. The
code above would produce this:
Name: Jason
One: 50
Two: 75
The parameters can also be file names if you like. Now you can enter quick custom
commands in one line. Enjoy, technophiliacs!
Working them Files
Files can be read and written to in a number of ways in Unix, and shell programming
takes huge advantage of this. Firstly, let's look at the basic input-output of a file.
$> echo "Write this to a file" > file.txt
$> echo "Write this, too!" >> file.txt
$> cat file.txt
write this to a file
write this, too!
$> echo "Overwrite the file with this!" > file.txt
$> cat file.txt
Overwrite the file with this!
As you can see, the > command tells the echo command to write the first line to
file.txt, and the >> command tells echo to add the words as a new line in the file.
Each time we use the > command, it overwrites the entire file, replacing the contents.
The >> simply adds new content as a new line to the end.
Not to sound too redundant, but let's try this in a loop:
while read line #loop this while there is
#still a line to read
do #start the loop
echo $line #say the contents of the line
done < file.txt #use this file.txt as the input
This crazy looking thing is best read almost backwards. The file, called file.txt, is
input on the done line, one line of the file at a time. When the while command tries to
read the file, it sees only one line of the file each time through the loop until there
are no more new lines.
Now let's imagine we have a file called example.txt that looks like this:
Jason 50 75
Groce 100 299
You can also store the name of the file in a variable and use the variable in place of
the file name after the < symbol. Using the following while loop, we can manipulate
this a bit more.
filename="example.txt" #make a variable
while read name num1 num2 #use the line from the
#file to read variables
do #start the loop
echo "Name: $name" #say the name
echo "One: $num1" #say the first number
echo "Two: $num2" #say the second number
done < filename #use example.txt to
#input lines of variables
The output would look something like this:
Name: Jason
One: 50
Two: 75
Name: Groce
One: 100
Two: 299
Code away, techies!
While-Do Loopy and Case-Esac Overstatements
By now, I hope everyone know if-then statements. Just in case, here's a super quick
example:
if [ $num -eq 5 ]
then
echo "The number is 5!"
fi
If something is true, then do this, and end the command with "fi". While-do loops and
case-esac statements aren't much different. A quick example for while:
typeset -i num=0 #create an integer,
#not always used for while,
#just an example
while [ $num -lt 5 ] #keep doing this while
#num is less than 5
do #start loop
echo "$num" #say the number num
num=$num+1 #add 1 to number
done #done with this loop
By adding other commands, the while loop can get to look very complicated, but the basic
archetecture is the same each time. Now for an example case-esac:
read input #read input from the user,
#again just an example
case $input in #use the variable $input
1) echo "one";; #if input is "1", say "one"
2) echo "two";; #if input is "2", say "two"
a) echo "AAA";; #if input is "a", say "AAA"
hello) echo "hi";; #if "hello", say "hi"
q) echo "goodbye;; #if "q", say "goodbye"
*) echo "huh?";; #if anything different
#than above, say "huh?"
esac #done with case statement
I hope this helps. Until next time, codemonkeys!
Tuesday, November 15, 2011
Programming in Unix 101
Let's go over a few programming basics, as we haven't gotten a proper review of them in class just yet. A program contains variables, parameters and arguments that can be acted upon by commands. For example:
This would return a list of files in long format containing the word name in the title. The argument, in this instance "name", can also be replaced by a variable, which would be represented by a $ followed by the variable name, such as $NAME.
A variable is merely a container for something, such as a string (ie, a word) or an integer (a number). Strings cannot be added, subtracted, etc, but integers can. (Note: an integer is a whole number, without a decimal point.) To create a string variable, simply decide on a name and tell it to store something.
However, to create an integer variable, it needs be made into the type integer. This command should work better:
These can be handy, but don't do much sitting out in the open without a script file. Creating a script file is as easy as making a file executable and editing the contents with an editor like vi. The easiest way to create a file to edit with vi is like this:
Make sure you're in the directory you want to create the file in, or
specify the directory you want to use when typing the command (vi
folder/filename). Now inside vi, it's time to create a script. (In vi,
press i to use input mode, and escape to enter command mode.) It's a
good idea to start the script with this:
The # indicates a comment, and will not run a command, but this special
line also tells the shell to run this in the bash or Bourne Again Shell,
so that any commands used in the script will work like normal to the
shell used in class. The next few lines should contain some information
about the file for future editing purposes:
Now let's get to programming. We need a function for this script to
accomplish. How about finding out how old you are in seconds? For
this, we need to ask the user some information and act upon that
information. Let's get the name and birthdate for the user first:
Now it's time for some crazy math fun (okay, this is a bit out there, sorry):
Fairly precise, this subtracts the length of time between the creation of Unix and the $bday variable from now. And finally, to display the output of the script:
There we have it! Save the file (in vi, use shift+Z+Z to save and close or :w filename to save as a new file), and run the script:
The reason for the ./ is because the $PATH variable used to identify the default location of programs does not include the path to the script just created. (Remember figlet?)
Enjoy, script-kiddies!
Command Parameter Argument
ls -l name
This would return a list of files in long format containing the word name in the title. The argument, in this instance "name", can also be replaced by a variable, which would be represented by a $ followed by the variable name, such as $NAME.
A variable is merely a container for something, such as a string (ie, a word) or an integer (a number). Strings cannot be added, subtracted, etc, but integers can. (Note: an integer is a whole number, without a decimal point.) To create a string variable, simply decide on a name and tell it to store something.
NAME="Jason"
However, to create an integer variable, it needs be made into the type integer. This command should work better:
typeset -i AGE=28
These can be handy, but don't do much sitting out in the open without a script file. Creating a script file is as easy as making a file executable and editing the contents with an editor like vi. The easiest way to create a file to edit with vi is like this:
vi filename
Make sure you're in the directory you want to create the file in, or
specify the directory you want to use when typing the command (vi
folder/filename). Now inside vi, it's time to create a script. (In vi,
press i to use input mode, and escape to enter command mode.) It's a
good idea to start the script with this:
#!/bin/bash
The # indicates a comment, and will not run a command, but this special
line also tells the shell to run this in the bash or Bourne Again Shell,
so that any commands used in the script will work like normal to the
shell used in class. The next few lines should contain some information
about the file for future editing purposes:
#
#Script by Jason Groce
#This is an example script
#Created 11/15/2011
#Last Edited 11/15/2011
#
Now let's get to programming. We need a function for this script to
accomplish. How about finding out how old you are in seconds? For
this, we need to ask the user some information and act upon that
information. Let's get the name and birthdate for the user first:
echo
echo "What is your name? "
read yourname
echo ""
echo "What is your birthdate? (yyyymmdd)"
read bday
echo ""
Now it's time for some crazy math fun (okay, this is a bit out there, sorry):
#Seconds elapsed
typeset -i seconds=$(date +%s)-$(date -d $bday +%s)
Fairly precise, this subtracts the length of time between the creation of Unix and the $bday variable from now. And finally, to display the output of the script:
echo "Hello, $yourname, you are $seconds seconds old!"
There we have it! Save the file (in vi, use shift+Z+Z to save and close or :w filename to save as a new file), and run the script:
[f52560@bearybear ~]$ ./filename
What is your name?
Jason Groce
What is your birthdate? (yyyymmdd)
19830221
Hello, Jason Groce, you are 906751610 seconds old!
The reason for the ./ is because the $PATH variable used to identify the default location of programs does not include the path to the script just created. (Remember figlet?)
Enjoy, script-kiddies!
Tuesday, November 8, 2011
More links:
Class website, for at home access:
https://linuxsandbox.coleman.edu/~pbille/com259/index.html
Scripting
A tutorial on scripting, with some examples:
http://www.dartmouth.edu/~rc/classes/ksh/
Another tutorial site, similar in flavor to the last:
http://steve-parker.org/sh/sh.shtml
Compression
A short description of compression:
http://www.devdaily.com/unix/edu/examples/compress.shtml
And a longer description of compression:
http://www.kingcomputerservices.com/unix_101/compressing_files_in_unix.htm
Utilities
A list of Unix utilities, most of the links don't work, but you can find these in my first post in the links to command listings:
http://parallel.vub.ac.be/documentation/linux/unixdoc_download/Utilities.html
And a bit of THOROUGH info for some commands:
http://www.people.fas.harvard.edu/~lipoff/miscellaneous/unix.html
Goodnight, nerdlings!
-Jason
https://linuxsandbox.coleman.edu/~pbille/com259/index.html
Scripting
A tutorial on scripting, with some examples:
http://www.dartmouth.edu/~rc/classes/ksh/
Another tutorial site, similar in flavor to the last:
http://steve-parker.org/sh/sh.shtml
Compression
A short description of compression:
http://www.devdaily.com/unix/edu/examples/compress.shtml
And a longer description of compression:
http://www.kingcomputerservices.com/unix_101/compressing_files_in_unix.htm
Utilities
A list of Unix utilities, most of the links don't work, but you can find these in my first post in the links to command listings:
http://parallel.vub.ac.be/documentation/linux/unixdoc_download/Utilities.html
And a bit of THOROUGH info for some commands:
http://www.people.fas.harvard.edu/~lipoff/miscellaneous/unix.html
Goodnight, nerdlings!
-Jason
Messaging in Unix
First, you need to know who to message. To get a list of online users, you could type:
~ : who
f52560 pts/26 2011-11-08 19:00 (10.10.30.116)
f66420 pts/28 2011-11-08 19:22 (10.10.30.107)
f51970 pts/31 2011-11-08 19:16 (10.10.30.104)
f57980 pts/32 2011-11-08 18:03 (10.10.30.105)
pbille pts/36 2011-11-08 14:34 (10.10.30.170)
f49150 pts/37 2011-11-08 18:07 (10.10.30.102)
f56340 pts/42 2011-11-08 19:21 (10.10.30.101)
pbille pts/44 2011-11-08 19:22 (10.10.30.170)
f57870 pts/40 2011-11-08 19:25 (10.10.30.110)
f53490 pts/45 2011-11-08 19:22 (10.10.30.106)
f55930 pts/46 2011-11-08 19:23 (10.10.30.108)
f57710 pts/47 2011-11-08 19:23 (10.10.30.112)
f56600 pts/49 2011-11-08 19:27 (10.10.30.111)
f56340 pts/50 2011-11-08 19:24 (10.10.30.101)
f54110 pts/51 2011-11-08 19:27 (10.10.30.113)
But the list you get, while it has usernames, doesn't have real names, and is not really useful if the username is something like f52560. So, let's try this:
~ : finger
Login Name Tty Idle Login Time Office Office Phone
f49150 RICHARD LUJAN pts/37 Nov 8 18:07 (10.10.30.102)
f51970 JONATHAN TAN pts/31 Nov 8 19:16 (10.10.30.104)
f52560 JASON GROCE pts/26 Nov 8 19:00 (10.10.30.116)
f53490 MARK TELLES pts/45 Nov 8 19:22 (10.10.30.106)
f54110 NICHOL GOLSTON pts/51 Nov 8 19:27 (10.10.30.113)
f55930 ALEXAND NIMLEY pts/46 Nov 8 19:23 (10.10.30.108)
f56340 JUST RODRIGUEZ pts/42 4 Nov 8 19:21 (10.10.30.101)
f56340 JUST RODRIGUEZ pts/50 Nov 8 19:24 (10.10.30.101)
f56600 DAVI MCPHERSON pts/49 Nov 8 19:27 (10.10.30.111)
f57710 DAVID SILVA pts/47 Nov 8 19:23 (10.10.30.112)
f57870 GASP HERNANDEZ pts/40 Nov 8 19:25 (10.10.30.110)
f57980 ANGEL M ANGULO pts/32 Nov 8 18:03 (10.10.30.105)
f66420 Michael Respicio pts/28 Nov 8 19:22 (10.10.30.107)
pbille Paul Bille pts/36 4:36 Nov 8 14:34 (10.10.30.170)
pbille Paul Bille pts/44 Nov 8 19:22 (10.10.30.170)
pbille Paul Bille pts/52 Nov 8 19:27 (10.10.30.170)
Now we get usernames and the actual name. With this, we can try something like:
~ : write f52560
write a message here
(CTRL + D)
This will send a message to the specific user. You can only send a message to one user at a time, and can send multiple lines of text. Pressing the CONTROL key and the D key at the same time exits the message and brings you back to the command entry mode.
Now, for the fun one. Broadcasting a message, so that EVERYONE on the server receives it. Be careful, because this means EVERYONE!
~ : wall
This is a message to EVERYONE!
(CTRL + D)
Enjoy your firecrackers, kiddles! Don't put out an eye!
-Jason
~ : who
f52560 pts/26 2011-11-08 19:00 (10.10.30.116)
f66420 pts/28 2011-11-08 19:22 (10.10.30.107)
f51970 pts/31 2011-11-08 19:16 (10.10.30.104)
f57980 pts/32 2011-11-08 18:03 (10.10.30.105)
pbille pts/36 2011-11-08 14:34 (10.10.30.170)
f49150 pts/37 2011-11-08 18:07 (10.10.30.102)
f56340 pts/42 2011-11-08 19:21 (10.10.30.101)
pbille pts/44 2011-11-08 19:22 (10.10.30.170)
f57870 pts/40 2011-11-08 19:25 (10.10.30.110)
f53490 pts/45 2011-11-08 19:22 (10.10.30.106)
f55930 pts/46 2011-11-08 19:23 (10.10.30.108)
f57710 pts/47 2011-11-08 19:23 (10.10.30.112)
f56600 pts/49 2011-11-08 19:27 (10.10.30.111)
f56340 pts/50 2011-11-08 19:24 (10.10.30.101)
f54110 pts/51 2011-11-08 19:27 (10.10.30.113)
But the list you get, while it has usernames, doesn't have real names, and is not really useful if the username is something like f52560. So, let's try this:
~ : finger
Login Name Tty Idle Login Time Office Office Phone
f49150 RICHARD LUJAN pts/37 Nov 8 18:07 (10.10.30.102)
f51970 JONATHAN TAN pts/31 Nov 8 19:16 (10.10.30.104)
f52560 JASON GROCE pts/26 Nov 8 19:00 (10.10.30.116)
f53490 MARK TELLES pts/45 Nov 8 19:22 (10.10.30.106)
f54110 NICHOL GOLSTON pts/51 Nov 8 19:27 (10.10.30.113)
f55930 ALEXAND NIMLEY pts/46 Nov 8 19:23 (10.10.30.108)
f56340 JUST RODRIGUEZ pts/42 4 Nov 8 19:21 (10.10.30.101)
f56340 JUST RODRIGUEZ pts/50 Nov 8 19:24 (10.10.30.101)
f56600 DAVI MCPHERSON pts/49 Nov 8 19:27 (10.10.30.111)
f57710 DAVID SILVA pts/47 Nov 8 19:23 (10.10.30.112)
f57870 GASP HERNANDEZ pts/40 Nov 8 19:25 (10.10.30.110)
f57980 ANGEL M ANGULO pts/32 Nov 8 18:03 (10.10.30.105)
f66420 Michael Respicio pts/28 Nov 8 19:22 (10.10.30.107)
pbille Paul Bille pts/36 4:36 Nov 8 14:34 (10.10.30.170)
pbille Paul Bille pts/44 Nov 8 19:22 (10.10.30.170)
pbille Paul Bille pts/52 Nov 8 19:27 (10.10.30.170)
Now we get usernames and the actual name. With this, we can try something like:
~ : write f52560
write a message here
(CTRL + D)
This will send a message to the specific user. You can only send a message to one user at a time, and can send multiple lines of text. Pressing the CONTROL key and the D key at the same time exits the message and brings you back to the command entry mode.
Now, for the fun one. Broadcasting a message, so that EVERYONE on the server receives it. Be careful, because this means EVERYONE!
~ : wall
This is a message to EVERYONE!
(CTRL + D)
Enjoy your firecrackers, kiddles! Don't put out an eye!
-Jason
Labels:
Coleman,
firecracker,
school,
University,
Unix
Review Time!
I found a few articles that may be useful. First up is "Learn UNIX in 10 minutes." It seems pretty decent, and goes over pretty much everything we have learned so far:
http://freeengineer.org/learnUNIXin10minutes.html
Next up, here's a tutorial for beginners, with lesson plans and screen shots. Not much beyond what we've learned so far, but good for review:
http://www.ee.surrey.ac.uk/Teaching/Unix/
From that site, we find a link to recommended books. From what I've found, these are the best ones out there, and are recommended on many Unix sites and forums:
http://www.ee.surrey.ac.uk/Teaching/Unix/books-uk.html
Now for another rare find: a free book on Unix from 1993, "Unix is a four letter word." It's an interesting read, covers a pretty thorough history of Unix and commands, and has a touch of geek humor. Okay, so it's 18 years old, and dates back before the Internet, but I find it valuable enough to read it, so maybe you will, too:
http://unix.t-a-y-l-o-r.com/index.html
See you at the midterm!
-Jason
EOF
http://freeengineer.org/learnUNIXin10minutes.html
Next up, here's a tutorial for beginners, with lesson plans and screen shots. Not much beyond what we've learned so far, but good for review:
http://www.ee.surrey.ac.uk/Teaching/Unix/
From that site, we find a link to recommended books. From what I've found, these are the best ones out there, and are recommended on many Unix sites and forums:
http://www.ee.surrey.ac.uk/Teaching/Unix/books-uk.html
Now for another rare find: a free book on Unix from 1993, "Unix is a four letter word." It's an interesting read, covers a pretty thorough history of Unix and commands, and has a touch of geek humor. Okay, so it's 18 years old, and dates back before the Internet, but I find it valuable enough to read it, so maybe you will, too:
http://unix.t-a-y-l-o-r.com/index.html
See you at the midterm!
-Jason
EOF
Monday, November 7, 2011
Unix notes, for a better tomorrow.
I get the feeling that most of us in the Unix class aren't taking much away from the lessons. Maybe it's time to take the learning into our own hands, and maybe we'll get further than the 2-steps forward and 1-step back approach we've encountered thus far.
First, let's drop the physical book and find a digital copy, for free. A simple Google search for the ISBN of the book, and here's a great link:
It's 6.7 Mb, so don't expect the school network to make it an easy download; I suggest you get it at home if you need/want it.
Now for a decent command listing:
Just in case you are feeling a bit masochistic, I also found a free book about Unix text processing from 1988. It's old, references things like dot-matrix printers, and has a lot of extraneous information, but it is useful in learning some vi commands and interesting Unix things. Also useful if you need a nap:
So, we've got the text, the reference card, and extra material. Now, what about a place to practice? Well, imagine this: an online terminal to try out, without needing to install anything special?
http://sdf.lonestar.org/ (click on "ssh" at the top right of the screen; requires Java)
Now maybe, just maybe, we have a viable environment to learn something on our time. Good luck, luddites. ;)
-Jason
Subscribe to:
Posts (Atom)