Please note that not all articles will appear in this archive page. You may prefer to search for specific articles via the search function on the main page...


King George?

Over at Old Horsetail Snake: Athletes in (In)Action, there is a "quiz" which includes (among other things), this question:

8. Six kings of England have been called George, the last one being George the Sixth. Name the previous five.

I have seen this question many times and it has always bothered me. Something in the cesspool of trivia that substitutes for a brain was nagging that there was something wrong with this question. I don't mean the obvious bit about 'king of England' - I know that should read 'Great Britain' or 'United Kingdom' depending on the era. What bothers me is the "George"...

So I checked. Guess what. There were six English kings who used the title "King George" (I through VI) but they were not all called George :-)

In fact, they were called (in order): Georg (note Germanic spelling), George, George, George, George and Albert.

So, next time someone asks that question, you know the real answer :-)

Posted by Ozguru at 06:00 AM | Comments (0)

The more things change...

Despite the fact that Windows Vista was rewritten from scratch (to get rid of legacy code) some of the legacy code is causing problems :-) In fact, Microsoft Ships First Vista Security Patches:

Microsoft Corp. has shipped the first critical security update for Windows Vista, the next version of its flagship operating system.
Over the weekend, the company released patches for beta testers running the Windows Vista December CTP (Community Technology Preview) and Windows Vista Beta 1, and warned that the new operating system was vulnerable to a remote code execution flaw in the Graphics Rendering Engine.
A Microsoft spokesperson told eWEEK that the Vista patches address the same vulnerability that led to the WMF (Windows Metafile) malware attacks earlier this month.

Well it looks like Windows XP Service Pack 3 Vista has the same problem as all previous releases of Windows. Looks like it might be time to try Linux or Mac :-)

Posted by Ozguru at 06:00 AM | Comments (0) | TrackBack

TechTip: Battle for Wesnoth (Cheat)

Q: I am playing Battle for Wesnoth on my Linux/Mac/Windblows (delete as appropriate) box and my character keeps getting killed.

A: Use the villages and/or healers.

Q: But isn't there a cheat or something?

A: Well .... yes.

Q: What is it?

A: Select a character and make sure the cursor stays over the character. Put the game into debug mode:

:debug[enter]

Now change the characters hitpoints and/or experience:
:unit hitpoints=1000[enter]
:unit experience=250[enter]

The first (hitpoints) is fairly safe, the second is risky if the character then gets upgraded to something that does not exist (this happens in a few of the optional downloads).

Note that with debug turned on, you can also create characters at will, anywhere on the map. You also get some debugging info cluttering up the top left hand corner of the screen which is inevitably where the baddies hang out...

Posted by Ozguru at 06:00 AM | Comments (1)

Forking

Q: I am writing some code that uses fork() and the output of the parent and child is getting mixed up.

A: This is to be expected given that the fork()ed process shares the standard out (stdout) and standard error (stderr) of the parent process. To get around this, the child could open some other file handle or you could make the parent wait until the child is dead. In the example code below, the first five parent messages should appear mixed with the child messages but the last five will appear *after* the child has finished. The magic bit is the waitpid() call.

Of course I have to mention the obligatory definition: Unix is where parents fork children and wait for them to die :-)

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
        int pid, i ;
        pid = fork() ;
        if (pid == 0)
        {
                /* This is the child process */
                for (i = 1; i <= 10; i++)
                {
                        fprintf(stderr, "Child message #%d\n", i) ;
                        sleep(1) ;
                }
        }
        else if (pid < 0)
        {
                /* Fork failed */
                fprintf(stderr, "Fork failed\n") ;
                exit(-1) ;
        }
        else
        {
                /* This is the parent process */
                int *status ;
                for (i = 1; i <= 5; i++)
                {
                        fprintf(stderr, "Parent message #%d\n", i) ;
                        sleep(1) ;
                }
                waitpid(pid, status, 0) ;
                for (i = 6; i <= 10; i++)
                {
                        fprintf(stderr, "Parent message #%d\n", i) ;
                        sleep(1) ;
                }
        }
        exit(0) ;
}

If you are having trouble following the code, let me know via email and I'll will walk through it...

Posted by Ozguru at 06:00 AM | Comments (0)

Unix Error Messages

[Found at Gotterdammerung where the motto is "Always remember to pillage before you burn!" ...]

At the USENIX Association conference in Atlanta recently [Ed: 1985/1986] a contest was held to invent the most humorous/bizarre/etc UN*X error message of the errno(2) 'EERROR' type. This contest had been tried at an earlier European Users Group meeting, where the winning entry was:
ENOTOBACCO - Read on an empty pipe
You get the idea. A partial [alphabetized] list of 'top(?)' entries from Atlanta [and from several readers of hp.unix] follows; if your pun/wierdness tolerance is low, you may want to abandon ship:
EBEFOREI - Invalid syntax
ECHERNOBYL - Core dumped
ECRAY - Program exited before being run
EDINGDONG - The daemon is dead
EFLAT - System needs tuning
EGEEK - Program written by inept Frat member
EIEIO - Here-a-bug, there-a-bug, ....
EIUD - Missing period
ELECTROLUX - Your code could stand to be cleaned up
EMILYPOST - Wrong fork
END.ARMS.CONTROL - Silo overflow
ENOHORSE - Mount failed
ENONSEQUETOR - C program not derived from main(){printf("Hello, world");}
EWATERGATE - Extended tape gap
EWOK - Aliens sighted
EWOK - Your code appears to have been stir-fried
EWOULDBNICE - The feature you want has not been implemented yet

And finally, a sort-of 'period piece':
EMR.ED -

A host is a host,
From coast to coast
And nobody talks to a host that's close,
Unless the host that isn't close
Is busy, hung, or dead.

I would also like this new signal to be supported:
SIGNUKE - Nuclear event occurred (cannot be caught or ignored :-)

Posted by Ozguru at 06:00 AM | Comments (0)

Hex Converter

There is a magic string that you feed to dc when you want to convert a hex number to a decimal:

echo "16 10 o i FF p" | dc

The idea is that you can convert any base 16 number to a decimal easily. Although the string looks arbitrary it is actually quite meaningful if I tell you that dc is an RPN calculator (more jargon). How about a step by step example (if you type this in, ignore the comments - lines that start with a '#' character):


# Start the program dc (probably /usr/bin/dc)
$ dc
# Add 16 to the stack (another bit of jargon)
16
# Add 10 to the stack (on top of the 16)
10
# Take the top stack value (10) for the output radix (i.e. base)
o
# Take the top stack value (16) for the input radix
i
# Chuck any old hex number onto the stack
DEADBEEF
# Print the top stack value out
p
3,735,928,559

Intelligent readers should be able to use the same method to convert decimal to binary.....

Posted by Ozguru at 06:00 AM | Comments (0)

UNIX is a drug

At first, I just did it on weekends. With a few friends, you know... We never wanted to hurt anyone. The girls loved it. We'd all sit around the computer and do a little UNIX. It was just a kick. At least that's what we thought. Then it got worse.

It got so I'd have to do some UNIX during the weekdays. After a while, I couldn't even wake up in the morning without having that crave to go do UNIX. Then it started affecting my job. I would just have to do it during my break. Maybe a 'grep' or two, maybe a little 'more'. I eventually started doing UNIX just to get through the day. Of course, it screwed up my mind so much that I couldn't even function as a normal person.

I'm lucky today, I've overcome my UNIX problem. It wasn't easy. If you're smart, just don't start. Remember, if any weirdo offers you some UNIX,

Just Say No!

This article was originally posted in April 2004.....

Posted by Ozguru at 06:00 AM | Comments (7)

Unix Users

I needed to use this for a presentation and given how hard it was to find, I figured I should pass it on...

2005-11-11--Dilbert_Unix.jpg

Posted by Ozguru at 06:00 AM | Comments (1)

Unexpected disconnect (SCSI)

Q: "Fatal SCSI error at script address 10 Unexpected disconnect. Can't open boot device"

A: There are three possibilities - you have a SCSI mismatch, your cables are shot or the termination is stuffed.

The first thing to check is that your devices match. Look at the bits of equipment where the SCSI cables connect and check for the symbols. You should find one of these four symbols:

SCSI_SE.jpg

This is the oldest SCSI type shown here. SE (Single Ended) SCSI is very common but suffers from noise and severe limits on the potential cable length. Common configurations may limit the number of devices to 7 (although technically Ultra SCSI goes to 15). Usually the problem is not one of addressing but of total cable length.
SCSI_HVD.jpg

HVD (High Voltage Differential), sometimes just called "differential" has been around for a while (Since SCSI-2). All the signals are 5V and this introduces a new set of problems but it does allow for longer (and less noisy) connections than SE.
SCSI_LVD.jpg

LVD (Low Voltage Differential) combines the best features of HVD (long cables) without the problems of carrying high voltage signals. This reduces the heat, consumes less power and can run at a higher speed. It was introduced with SCSI-3. Most modern equipment will use this.
SCSI_LVD_MSE.jpg

LVD/MSE looks like a cross between the LVD and SE signals - guess what ... it is. A device that is LVD/MSE will operate in either mode depending on what it is connected to. This is useful when plugging newer devices into older equipment but it does have the drawback of limiting length and reducing the bus speed (which affects all devices on the bus).

Back to our problem, if you try to mix and match different types (with the exception of LVD/MSE) then you will inevitably get the "Unexpected disconnect". Effectively it means "don't do this". There are expensive convertors but it is easier to change the device or the card.

Possibility number two was damaged cables. This is especially true of older cables (80 pin or 68 pin) - check that none of the pins are bent or out of alignment. Try replacing the cables to see if it helps with the problems. If you are using SE, remember there are strict limits on the total length of the SCSI bus (including the bits you can't see - inside the devices).

Finally, check that you have proper termination. Some devices are self-terminating (there should be a 'TERM' light) and others require an external terminator. Like all the other devices, make sure this is the same type as all the devices on the chain. You cannot mix and match (except for LVD/MSE).

Posted by Ozguru at 06:00 AM | Comments (0)

Unix Expertise

People often ask why "guru" in my handle. Does it mean that I meditate up a high mountain? Well, I found the perfect explanation in a ranking system for Unix people. Some of the concepts are a bit dated but I can proudly claim to meet all the criteria for Guru - but not all the criteria for Wizard...

People who come into contact with the UNIX system are often told : "If you have trouble, see so-and-so, he's a guru", or "Bob there is a real Unix hacker". Often they are baffled by these appellations, and do not pursue the matter further. What is a "Unix Hacker ?". How does he differ from a "guru" ? To answer these and other questions, here is the UNIX HIERARCHY :
  • beginner

    • insecure with the concept of a terminal

    • has yet to learn the basics of vi

    • has not figured out how to get a directory

    • still has trouble with typing <RETURN> after each line of input

  • novice
    • knows that ls will produce a directory

    • use the editor, but calls it vye.

    • has heard of C but never used it

    • has had his first bad experience with rm

    • is wondering how to read his mail

    • is wondering why the person next to him seems to like Unix so very much

  • user
    • uses vi and nroff, but inexpertly

    • had heard of regular-expr's but never seen one

    • uses egrep to search for fixed strings

    • has figured out that '-' precedes options

    • is wondering how to move a directory

    • has attempted to write C program and has decided to stick with pascal

    • thinks that sdb is a brand of stereo component

    • knows how to read his mail and is wondering how to read the news

  • knowledgeable user
    • uses nroff with no trouble, and is beginning to learn tbl and eqn

    • thinks that fgrep is fast grep

    • has figured out that mv will move directories

    • has learned that learn doesn't help

    • somebody has shown him how to write C programs

    • once used sed to do some text substitution

    • has seen sdb used but does not use it himself

    • thinks that make is only for wimps

  • expert
    • uses sed when necessary

    • uses macro's in vi, uses ex when necessary

    • posts news at every possible opportunity

    • writes csh scripts occasionally

    • writes C programs using vi and compiles with cc

    • has figured out what && and || are for

    • thinks that human history started with !h

  • hacker
    • uses sed and awk with comfort

    • uses undocumented features of vi

    • writes C code with cat > and compiles with !cc

    • uses adb because he doesn't trust source debuggers

    • can answer questions about the user environment

    • writes his own 'nroff' macros to supplement standard ones

    • writes scripts for Bourne shell (/bin/sh)

  • guru
    • uses m4 and lex with comfort

    • writes assembly code with cat >

    • uses adb on the kernel while system is loaded

    • customizes utilities by patching the source

    • reads device driver source with his breakfast

    • can answer any Unix question after a little thought

    • uses make for anything that requires two or more distinct commands to archive

    • has learned how to breach security, but no longer needs to try

  • wizard
    • writes device drivers with cat >

    • fixes bugs by patching the binaries

    • can answer any question before ask

    • writes his own troff macro packages

    • is on first-name basis with Dennis, Bill and Ken

Posted by Ozguru at 06:00 AM | Comments (3)

OpenSSH 4.2p1

2005-09-01--OpenSSH.gif
Get yours while it's hot....

Posted by Ozguru at 06:00 AM | Comments (0)

TechTip: Crontab

Q: Help! I am trying to edit the cron file for sys and I used "crontab -e sys" and the system just gave back an error number and then hung.

A. Nope. Actually it didn't. What you are seeing is a bit of archaeological history:
# crontab -e sys
305

You are talking to ed - not the horse, the original editor - the one that came before vi. Simply type the letter 'q':
# crontab -e sys
305
q
The crontab file was not changed.
#

To use vi (or some other editor), you need to set the EDITOR environment variable (on older systems, you can set the VISUAL variable):
# EDITOR=/usr/bin/vi
# export EDITOR

Now, running crontab will get you into vi (or whatever you specified). Note that the same variable will also fix a number of other programs (like sudo) so you may want to add it to your .profile (or equivalent).

Posted by Ozguru at 06:00 AM | Comments (2)

TechTip: Static Route? Gateway? Speak English...

Q: My server can't see Fred's server.

A: Do you have a route to it?

Q: What is a route?

A route is a set of directions that tell the computer how to send traffic to various destinations. You can see the current route table (even under windblows) by asking nicely:

bash-2.05# netstat -rn
Routing Table: IPv4
Destination Gateway Flags Ref Use Interface
-------------------- -------------------- ----- ----- ------ ---------
10.0.0.0 10.0.0.83 U 1 2907 hme0
224.0.0.0 10.0.0.83 U 1 0 hme0
default 10.0.0.8 UG 1 622
127.0.0.1 127.0.0.1 UH 2 3467 lo0

The -r displays the route table and the -n means to use numeric addresses (don't resolve them using DNS*).

We can ignore the 127.0.0.1 (loopback interface) and the 224.0.0.0 (multicast datagrams). That leaves us with a route to 10.0.0.0 (a network address) via 10.0.0.83 (our address) and a route to default (another network address) via 10.0.0.8 (some arbitrary ip address). Notice the flags (U, UG or UH), the 'U' means up, the 'G' means gateway and the 'H' means host. Note that the lack of a H implies that we are talking about a network route.

This table tells the sever that it can talk directly to the 10.0.0.0 network or at least some minor part of it. How much of the network we can talk to is governed by the netmask (which we are not going to discuss today). The table also says that all other requests should be sent to a gateway which has the address 10.0.0.8. Note that the gateway (or router) is on a network we can talk to (10.0.0.0). A gateway with some other address (say 142.68.81.93) would be useless because we would have no way to reach the gateway :-)

This table is normally build and maintained dynamically by the operating system but it is possible to add temporary changes:

route add net 10.0.2.0 10.0.0.52 1

The numbers are network (10.0.2.0), gateway / router (10.0.0.52) and hops (1). The hop-count is a way of telling the system how far away a particular gateway happens to be. This is used to make sure there are no loops in the route topology and can also be used to penalise a slower link**.

What if you wanted to make this route permanent? Enter the /etc/gateways file (which is very poorly documented on Solaris). Each line in the file should look like:

net <remote-network-ip> gateway <gateway-ip> metric <hop-count> passive
or
net <remote-network-ip> gateway <gateway-ip> metric <hop-count> active

If the gateway is really permanent, use the keyword 'passive'. Otherwise (keyword 'active') the operating system will occasionally check the route and delete it from the routing table if it appears to be down. Note that the gateway will be recreated on the next boot unless you remove the entry from the gateways file.

[* This is important if you are trying to work out why you can't see the DNS server. Leaving the -n will hang netstat as it does heaps and heaps of lookups...]

[** Say you have a high-speed route and a slow-speed route to a particular gateway. You would give the slow-speed router a higher hop-count (i.e. claim that it is further away) so that the high-speed route is used. If for some reason, the high-speed router fails, the system will "fall back" to using the low-speed route.]

Posted by Ozguru at 06:00 AM | Comments (0)

TechTip: What the heck is a token ring?

Is that like an engagement ring but you don't really mean it?

See, I even get to answer the strange questions. This question is not all that strange if you know a bit about your computer history. Way back last century (early 1980s), it was not real clear which one of a number of competing network protocols would eventually become dominant. There was a "standard" (ISO) which everyone outside of Europe ignored, there was Token-Ring and there was Ethernet. Of course, we all *know* that Ethernet won out but in the early days that was not obvious for two reasons: TokenRing was plug and play (no dodgy thicknet taps or transceivers) and (according to IBM) it performed better. As time passed, ethernet got faster (10Mb -> 100Mb -> 1000Mb) and adapted the far more familiar phone-like connectors.

You can still run TokenRing on your Unix systems. For Sun servers, the two relevant cards are TRI/P (TokenRing Interface/PCI) and TRI/S (Sbus). The part numbers are X1039A and X1144A. I have seen the TRI/P card running under Solaris 7 and 8 and it should still be supported in 9. Note that there are some critical patches if you have a large token ring network. In fact one of the patches was the result of a bug (to do with MAC address translation) that I logged and researched :-)

My favourite comment on Token Ring is a Dilbert cartoon (see extended entry).

2005-07-20--Dilbert_Token_Ring.jpg

Posted by Ozguru at 06:00 AM | Comments (2)

My Application Won't Start

Q: I start my Unix application (apache2 in this case) but it exits straight away and there is no message or error. What's wrong?

A: Are you sure about the lack of an error message?

Q: Yes. The prompt comes back.

A: Are you really sure?

Q: Yes.

A: Are you really, really sure?

Q: Why?

A: Well a lot of Unix applications log their messages somewhere other than the screen where you launched them. They do this because it is unwise to assume that a terminal exists - the application could have been started from cron or another application. Instead they may write messages direct to a log file, to the system console or to the system log facility. You should check all of these.

To check the system console, use dmesg. This is available on most Unixes and will show you the last n messages written to the console (where n is an arbitrary number selected by your OS vendor). To check the system log facility, you need to find the log file. It might be something like /var/log/system.log (BSD, Mac) or /var/adm/messages (Solaris). You can check for sure by investigating the syslog configuration file /etc/syslog.conf which will contain a line something like:

*.notice;authpriv;kern.debug;mail.crit    var/log/system.log

Finally, the application may have it's own log (as it does in the case of apache2). You could try guessing where this is located or you can use the administrator's second best friend*: truss(1). You invoke this (assuming that your OS has the program) as truss -f myapplication. This will generate a *lot* of output so you need to make sure you can scroll back through it (or capture it to a file). Start at the beginning of the output and look for open(something) = n where n is the relevant filehandle. Write down n and the name of the file. Keep scrolling and recording the open entries and look for write(n,....). This indicates that the program has written a message to a file and the file number (n) will match one of the open calls. Now you go find the file and check the messages.

In this particular case, apache2 is failing because the group 'nobody' is not defined.

[* The administrator's best friend would probably be fuser.]

Posted by Ozguru at 06:00 AM | Comments (0)

Days Difference in Shell

Question: I want to calculate the number of days between two dates in shell.

Answer: Current versions of ksh can do some magic using printf.

#!/bin/ksh DATE1=`printf '%(%s)Tn' 'Oct 6 07:51:55 2004'` DATE2=`printf '%(%s)Tn' 'May 14 12:00:42 2005'` SECS=`expr $DATE2 - $DATE1` MINS=`expr $SECS / 60` HRS=`expr $MINS / 60` DAYS=`expr $HRS / 24` echo $DAYS

Obviously you can adapt this as required. Remember with expr to keep spaces around the operators...

Posted by Ozguru at 06:00 AM | Comments (3)

Self printing code

Question: Can you write a program that prints itself?

Answer: Yup.

#!/usr/bin/perl -w
#
seek(DATA, 0, 0) ;
while()
{
        print ;
}
__DATA__

Posted by Ozguru at 06:00 AM | Comments (0)

Vi is missing

Help me, I deleted vi....

Don't laugh - it can happen. In this case, it is not a serious problem because there are usually multiple links to vi.

Find the directory where vi used to be (probably /usr/bin):

bash# ls -li vedit
        245 -r-xr-xr-x   5 root     bin       227956 Nov 26  2003 vedit

The inode (leftmost number is 245). For interest, you can check which other files also have this inode in this directory:

bash# ls -i | grep " 245 "
       245 edit
       245 ex
       245 vedit
       245 view

Now link any one of these to vi: ln ex vi. Done.

Note that you may not be so lucky if you are using BSD/Linux because they are more likely to use softlinks:

user$ ls -li | grep vim

1080938 lrwxr-xr-x 1 root wheel 3 Mar 30 22:51 ex -> vim

1080939 lrwxr-xr-x 1 root wheel 3 Mar 30 22:51 rview -> vim

1080940 lrwxr-xr-x 1 root wheel 3 Mar 30 22:51 rvim -> vim

1080942 lrwxr-xr-x 1 root wheel 3 Mar 30 22:51 view -> vim

1080943 -rwxr-xr-x 1 root wheel 1040376 Mar 21 21:12 vim

1080944 lrwxr-xr-x 1 root wheel 3 Mar 30 22:51 vimdiff -> vim

1080945 -rwxr-xr-x 1 root wheel 1068 Mar 21 21:12 vimtutor

In this case the fix would be: ln -s vim vi...

Posted by Ozguru at 06:00 AM | Comments (0)

Hard Links vs Soft Links

Someone pointed out that I had neglected the Tech Tips for the last two Fridays so I figured you were due an extra this week...

In Unix there are hard links and soft (symbolic) links. They are quite different:

  • A hard link is actually another directory entry that points to the same disk blocks
  • A soft link is a file which contains the path to another file

You never actually remove files on Unix, you decrement their hard link count. When it reaches zero, the file is effectively removed because there is no longer any way to reference it.

Consider the following:

user$ date > file1

user$ ln file1 file2

user$ ln -s file1 file3

user$ ls -li file*

1405281 -rw-r--r-- 2 user staff 29 Apr 21 09:38 file1

1405281 -rw-r--r-- 2 user staff 29 Apr 21 09:38 file2

1405284 lrwxr-xr-x 1 user staff 5 Apr 21 09:38 file3 -> file1

user$ cat file1

Thu Apr 21 09:38:14 EST 2005

user$ cat file2

Thu Apr 21 09:38:14 EST 2005

user$ cat file3

Thu Apr 21 09:38:14 EST 2005

user$ rm file1

user$ ls -li file*

1405281 -rw-r--r-- 1 user staff 29 Apr 21 09:38 file2

1405284 lrwxr-xr-x 1 user staff 5 Apr 21 09:38 file3 -> file1

user$ cat file2

Thu Apr 21 09:38:14 EST 2005

user$ cat file3

cat: file3: No such file or directory

The first command creates a file - this involves allocating some disk space (to hold the data). Then we create a hard link and a soft link. Note that the -i option to ls actually shows the real inode (i.e. the first block on the filesystem) and that this is identical for file1 and file2 - in otherwords, they are both references to the same thing.

When we cat the files, they are all the same. This is because Unix automatically dereferences the soft link (to find out where it goes) and then repeats the operation with the real file. This adds overhead to the call (because we have to look up two files - the soft link and then the file that the soft link points to) and should be kept in mind when looking at performance issues.

When we remove file1, the data still sits unchanged in the filesystem. It can be referenced via file2 but file3 is now useless because it no longer points to anything. Unix has no way of telling that file2 would be a reasonable replacement for file1.

Note that inodes are only unique within a filesystem and hence hard links do not work across filesystems. There is no way to create a hard link in say /var which connects to a file in /usr if the two are different filesystems.

Soft links cannot cope with the removal or relocation of the target file. Changing the target's name or directory will result in a "File not found" message.

Note that some operating systems (e.g. MacOS X) and some filesystems (AFS, HFS, HFS+) support another type of link called an alias. An alias is midway between a soft and a hard link. Effectively it is like a soft link to an inode. This is useful because, unlike a hard link, it can cross filesystem boundaries and it can cope, unlike a soft link, with the file path changing.

Posted by Ozguru at 06:00 AM | Comments (0)

Vi (or ViM)

I promised that today would be about vi (or vim) even though a better tip came along yesterday...

Vi is the grandfather of Unix editors - it was originally written by Bill Joy at UCB (yes the same Bill Joy who worked for Sun). Given the origins and the long history of the editor, you can bet that there must some hidden secrets.

Firstly, I need to explain to newcomers why vi is like it is and then I will move onto to showing how a pipe works in vi.

People who meet vi for the first time usually recoil in horror - where are the menus and mouse actions? Well vi was written at a time when those accessories did not exist - in fact you could run vi on terminals that did not even have arrow keys. To cater for such a limited hardware environment, the original design was for a pure modal editor - vi is either accepting instructions from you or it is adding text to the file. That mens if you are not getting the desired effect, you are probably in the wrong mode :-)

Command mode (where you tell vi to do things) is the default mode, you switch to text entry mode by using one of the commands that (a)dds or (i)nserts text (there are others as well such as (o)pen and (c)hange but the most common commands are 'a' and 'i'). To get back to command mode, you need to press the ESC key.

OK, you need to create a file on your nearest Unix box. If you want to play along, pick a directory with some files in it (like /tmp or you home directory). Let's call out file 'foo' (a time-honoured name for a scratch file):

vi foo

We are in command mode so type 'a' to add some text to the file. You will not see this 'a' on the screen. Type a few blank lines and then a line that contains the words:

ls -als

followed by a few more blank lines. Now hit ESC to get back command mode.

You can move around the file using the arrow keys (or if you don't have them, use 'h', 'j', 'k' and 'l'). Move the cursor to somewhere on the line with text on it. Exactly where on the line does not matter. Now we are going to trade this line for the results of a Unix command. Carefully type the following (including the colon):

:.!sh

(That was a ':', '.', '!' and the letters 's' and 'h'). The colon tells vi that we want to talk to the line editor underneath vi (ex), this is important because the way ex counts lines is a little different. The full stop says to use this line only. The exclamation mark says to pipe the left hand side (the line in the file) to the right hand side (the default Unix shell). When this returns, the results will replace the input line. You should have a long listing of all the files in your current directory inside your foo file.

Note that the command can be considerably more complicated and you can even chain commands together over multiple lines. Note that to send multiple lines to a pipe, you need to select them using the ':' and '.' operators. For example to pick the two lines before this one and one afterwards, we can say:

:.-2,.+1!sh

Note the use of a ',' to separate the left hand and right hand end of the range. If you want to know more about vi (or vim), drop me a line...

Posted by Ozguru at 06:00 AM | Comments (0)

Happy Hogmanay

TechTip: The State of the Demon Address

TechTip: Google Labs Aptitude Test (GLAT)

TechTip: Google Labs Aptitude Test (GLAT)

TechTip: Google Labs Aptitude Test (GLAT)

TechTip: RSS Validation

TechTip: Google Labs Aptitude Test (GLAT)

TechTip: AIX - the writing is on the wall....

TechTip: Google Labs Aptitude Test (GLAT)

Who wrote Linux?

TechTip: Floppy RAID

TechTip: Lotto Numbers

TechTip: Open Mail Relays

TechTip: Beyond Patching?

TechTip: TCP via Bongo?