Category: shell scripts


I was listening to the pauldotcom.com security podcast the other day and heard then talking about netcat.  This peaked my interests and got me thinking that I should be able to print text files from any Unix-based system on which netcat could be installed/compiled.  At first I tried it the simple way:

cat file.txt | nc 10.10.10.201 9100

This did indeed send the file to the printer’s port 9100.  There were two problems though.  First off, the printer asked me if I wanted to print the buffer or wait until it was finished printing.  Pushing the button on the printer made the file print but is not as convenient as it should be.  This problem can be fixed with a “-w1” switch.  This tells netcat to quit if the input stream is idle for more than 1 second.

cat file.txt | nc -w1 10.10.10.201 9100

This prints the text file almost instantaneously but there is another problem.  All the text is stair stepped.  As it turns out, Unix uses only newline character at the end of each line.  In dos and apparently network laser printers, a newline and a carriage return are two separate things that need to be handled individually.  A little bit of sed trickery is just the thing to fix this problem.

sed ‘s/$'”/`echo -e \\\r`/” file.txt | nc -w1 10.10.10.201 9100

Obviously you will need to put your own printer’s IP address there.  This will probably only work with a decent networked laser printer.  I’ve tested this with my Lexmark Optra T644 and it works great.  Special thanks to rkdavis for helping sort out the sed bits.

Sed is a very powerful tool when used correctly but can also be a source of frusteration at times.  One problem with it shows up when you are trying to identify and replace non-printable characters.  Luckily sed has a nice command line switch that will help you debug certain problems with sed.

When you just use cat to display a file, you’ll see it as you are normally used to but this isn’t how sed sees files.

cat hello.c

When you use the -n ‘l’, you’ll see the file how sed sees it.  (It’s a lower case “L” in the single quotes)

sed -n ‘l’ hello.c

Now you can see the new line characters at the end of the lines and the tabs that proceed some of the lines.

This is a nifty trick you can use to impress your friends.  Imagine you have some smallish program that you want to wrap up into a single file for simplicity.  Part of final output perhaps relies on a clever bit of shell scripting and another part relies on a binary of some sort that you need to get the job done.  Here’s a way to wrap it all up in a tidy little package:

#!/bin/sh
grep SRC: $0 | grep -v “grep SRC:” | sed -e s/SRC://g > /tmp/hello.c
gcc -o hello /tmp/hello.c
./hello
exit
SRC: #include <stdio.h>
SRC: int main(int argc, char *argv[])
SRC: {
SRC: printf(“Hello World\n”);
SRC: return 0;
SRC: }

Everything below exit is completely ignored by your shell.  The grep statement goes through the shell script line by line and returns the all the lines starting with “SRC: ” to sed.  Sed uses a simple regex to strip the “SRC: ” off your source code and sends the output to a file in your /tmp directory.  Then the file is compiled and ran.  You could go further and delete the source file out of the /tmp directory if you like or don’t bother.

My last article is nice for checking for a few dependencies in a shell script but if your user has to keep running your script and then go back and install something and run it again, this can get very tiresome.  It’s much nicer to give your user a big list of deps they need to install in one shot.  Here is some code to do just that.

failed_dep=0
if ! which pkg1 > /dev/null; then
echo “Please install pkg1 or make sure it is in your path”
failed_dep=1
fi
if ! which pkg2 > /dev/null; then
echo “Please install pkg2 or make sure it is in your path”
failed_dep=1
fi
if ! which pkg3 > /dev/null; then
echo “Please install pkg3 or make sure it is in your path”
failed_dep=1
fi
if ! failed_dep==1; then
exit
fi

Obviously remember to change the “which pkg” to the dependency you are looking for and change the echo statement to reflect this as well.  Just keep adding if blocks if you need to check for more than three packages.  If you have a LOT of dependencies, your end user will thank you for using this method.

Almost every shell script written depends on something else.  Many times those things are already on your computer.  Basic stuff like cat and echo are arguably on every unix distribution in the known universe.  Other things start to vary more widely between different distributions.  Stuff like dialog or perhaps even perl may not be on your system.  Especially if it’s a compacted or embedded system.  To give your shell script a nice polished feel that makes it more portable and easier to use, you should add a couple of lines of code to check and make sure any extra items are there first.  Here is an example that checks for :

if ! which perl > /dev/null; then
echo “Please install perl or make sure it is in your path”
exit
fi

This will help people quickly determine why your script is failing to run on their platform.  Futhermore, it will save you support emails and save users of your script frustration.  Especially if they are newer users who aren’t accustom to debugging scripting glitches.

Hello, world is the most basic of all test programs.  It’s one of the first steps to determine if you have your development environment set up correctly and is also a good first program to learn in any language because it will give you a good idea of the bare minimum requirements to build a program in a given language.

BASIC

Let’s start with Hello, World in basic since that was the first programming language I ever encountered.  The code is very simple:

10 PRINT “Hello, World”

RUN

10 is a line number which is a requirement of old basic compilers.  Generally the lines are numbered  10, 20, 30, etc although they don’t have to be.  Part of the reason for this is so you can later insert other line numbers into your code without renumbering all of your lines of code.  Newer BASIC implementations have sub-routines and other features have have allowed them to ditch the line numbers.  The program is executed from top to bottom so everything in basic has to be in order.  The command RUN at the bottom runs the program and will display your text.  It is not actually part of the program.

Ruby

In Ruby, there are two easy ways to do a hello world program.  I’ll assume you are using a Unix-based machine to try this example.  You’ll need to create a text file called hello.rb with a text editor.  The first way is:

puts ‘Hello, World’

Save your file and type ruby hello.rb at the command prompt.  If all went well, it should print Hello, World and then give you back your command prompt.  I’m assuming that you have installed ruby and it’s in your path.  On a Debian system, it’s easy to install ruby if it’s not already there.  Use a command such as sudo apt-get install ruby.  The other ruby hello world example is:

print(“Hello, World\n”)

C

Hello, World in C is far more complex than any of the other examples.  This is because C is highly structured and not very forgiving.  It also doesn’t have the printf function in the core language so the standard input and output library must be included.  I will also assume you are using a Unix environment for this example.  If you try to run this in a dos/windows environment it will probably fail.  Here is the hello world code in C:

#include <stdio.h>

int main(int argc, char *argv[])
{
printf(“Hello World\n”);
return 0;
}

To run it, you’ll need to put the code in a text file called hello.c.  Then type in gcc hello.c at the command prompt.  This should generate a file called a.out.  At the command prompt, type ./a.out to run the program.  Different compilers and environments may give different results.

Bash

The last example I’ll give is for bash scripting.  Some people would argue that bash is not a programming language but nevertheless it’s a very powerful way to accomplish tasks with other programs and it’s a good way to automate repetitive tasks.  Here is hello world in bash:

#!/bin/sh

echo “Hello, World”

To run this you could simply type the bottom line at the command prompt.  Instead, save it to a file called hello.sh.  Now before you run it, you’ll need to set the executable bit.  Type chmod 755 hello.sh at the command prompt.  Now you can type ./hello.sh to execute the script.

Command line drum and bass

I was flipping through the latest winter 2009-2010 issue of 2600 magazine the other day on my way up to a family vacation and an article caught my eye. The author of the article, SigFLUP, had written a program to use your computer keyboard to manipulate a looping wav file. After installing SoX & libSDL I fired up the program with the test loop that was provided.  The author posted a demo of what kinds of variations could be made on one loop.

The program is packaged in the form of a one-size-fits-all shell script that has C embedded in it which compiles at run time. It took a little bit to start up in my Debian VM. I’d say 20-30 seconds.  Once it fired up, I was presented with a blank window that had spawned from the terminal.  That’s when you know it’s ready to run.

I’m not entirely clear to me how the program runs but from the article in 2600 it seems that it maps the 16-bits of the wav to QWERTYUI & ASDFGHJK with Q being the least significant bit and K being the most significant bit.  To use the program, you press two or more of these keys.  What the program does is replaces the values in all of the bits you are pressing with 1 if any of the bits you are pressing are set to 1.  In other words, if you press QWE and the values of QWE were 001, the values of those would then become 111.  All of the other values remain the same.  As you can imagine, this leads to sound crazy sounds.  Listen to the demo to see what I mean.  SigFLUP says in the article that the loop should be a multiple of 65535 samples in length but if you are just going for effects that you can export to your sound editor, that doesn’t matter too much.  Don’t miss the pitch bender keys which are “Z” & “X”.

The program understandably has a few glitches or I just don’t know how to use it right, but nevertheless it makes for a really cool proof of concept that I would love to expand upon someday.  You can download the program here from SigFLUP’s site.

Powered by WordPress. Theme: Motion by 85ideas.