Am I connected remotely?

I now share my dotfiles between the various OS X machines I use daily, using Dropbox and symlinks.

However, I have many aliases and functions that need to act differently if I only have a console session at the machine in question, or a full GUI session.

With bash, this is easy to test:

1 export EDITOR='nano'
2 if [[ -z "$SSH_CONNECTION" && $OSTYPE =~ ^darwin ]]; then
3 export EDITOR='mate --wait'
4 export TEXEDIT='mate -w -l %d "%s"'
5 export LESSEDIT='mate -l %lm %f'
6 fi

Now, if I am remotely connected to a machine, then I will get nano as my editor, but if I am sitting directly in front of it, then it will open Textmate.

View man pages in Preview

It’s not a new concept, but here is my take on it:

 1 function man {
 2     # We can get the actual path to the man command here, so we can override
 3     # it with our function name.
 4     MAN=`which man`
 5     # Change these two if you are not on OS X.
 6     CACHE_DIR="${HOME}/Library/Caches/manpages"
 7     OPEN="open"
 8     
 9     # If we don't have any arguments, use the nice man error message
10     if [ ! $1 ]; then
11         $MAN
12         return
13     fi
14     
15     # If we have an argument that clashes with what we are wanting to be
16     # able to do, pass the whole command through.
17     for ARG in $*; do
18         case $ARG in 
19             -[dfkKwtWP])
20                 $MAN $*
21                 return;;
22         esac
23     done
24     
25     # Make sure our cache directory exists.
26     mkdir -p $CACHE_DIR
27     # Get the man page(s) that match our query.
28     MAN_FILES=`$MAN -w $*`
29     for MAN_FILE in $MAN_FILES; do
30         # Get the name of the man file, and the section.
31         MAN_PAGE=`basename "$MAN_FILE" | cut -d \. -f 1-2 | sed 's/\./(/' | sed 's/$/)/'`
32         # Our PDF will be in this location
33         PDF_FILE="${CACHE_DIR}/${MAN_PAGE}"
34         
35         # If we actually have a man file that matches
36         if [ -n "$MAN_FILE" ]; then
37             # See if the man file is newer than our cached PDF, and if it is,
38             # then generate a new PDF. This works even if $PDF_FILE does not
39             # exist.
40             if [ $MAN_FILE -nt $PDF_FILE ]; then
41                 $MAN -t $* | pstopdf -i -o "$PDF_FILE"
42             fi
43             # Then display the file.
44             $OPEN "$PDF_FILE"
45         fi
46     done
47 }

Tab completion and ssh/open -a

I use the Terminal just as much as the Finder, and have tab-completion turned on in bash. To make it better, you can set it so that it will complete differently depending upon what you have already typed in.

The first one of these tips will autocomplete from the ~/.ssh/known_hosts file, so that when you type in:

$ ssh ma[tab]

1 complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh

it will autocomplete the servers you ssh to that start with “ma”.

The next one is more complicated – it allows you to complete from all available applications when typing:

$ open -a [tab]

1 complete -W "$(/bin/lsregister -dump | /usr/bin/sed -E -n -e '/\/Applications/{s/^.+ ((\/Applications|\/Developer).+\.app)$/\1/p;}' | \/usr/bin/sed 's/ /\ /g' | \/usr/bin/sed -e s/\'/\\\'/g | /usr/bin/xargs /usr/bin/basename -s '.app' | /usr/bin/sed 's/ /\\\ /g')" open -a

These can be added to one of your bash startup files: mine live in ~/.bashrc.

Changing UNIX shell without actually changing it

Very rarely, I encounter a computer system I have to use regularly, but I don’t have superuser status on. Notably, at Uni, I have access to a SunOS system, where I actually have to use it from time to time. Most of the time this is just via ssh, but sometimes it’s a physical login to a SunRay workstation.

I much prefer bash over other shells, not because it is necessarily better, but that it is just the one I use most of the time. I’ve got some nice systems to help me out, like using a different colour for the user@host string on each machine, so I can easily see which machine the current ssh session is actually logged into.

However, at Uni there are lots of restrictions. We can run /usr/bin/bash, but we can’t change our default shell to it. In fact, we can’t change our default shell at all, which is kinda dumb. I’ve tried all sorts of tricks, but I just can’t do it.

The next step is to have your .login, or whatever, run the shell you want. For me, this is safe-ish, since tcsh (the current default shell) executes the contents of .login, but bash doesn’t. If you are using one shell that uses a particular login or profile file, and you want to change to another which uses the same file, you might struggle, or get stuck in an infinite loop. Which is probably worse.

Just having /usr/bin/bash -login in your .login file will then cause bash to run, and execute the contents of your .profile: without the -login it won’t execute the contents of said file. But what about when you exit the bash shell, using Ctrl-D, or exit, or logout, or whatever?

If you put a logout after the /usr/bin/bash -login line will cause the original shell to logout immediately after leaving the bash shell. Which is exactly what we want.

Now, all I need to do is figure out how to get rid of the line that says : tcsh: using dumb terminal settings.

That one’s too easy. Use xterm instead of xterm-color in the Settings➞Advanced area of the Terminal Preferences:

xterm-color.png

UNIX palindromes #1

Thoughts of the Bored » Archived Thought » UNIX palindromes #1

There exist a “test” command and a “tset” command, but tset does not do the reverse of test. I consider this a lost opportunity.

Getting Finder Comments in different languages

bash: mdls filename | grep FinderComment AppleScript: tell application "Finder"     comment of file end tell python: #!/usr/bin/pythonw from appscript import * path = '/Users/NAME/your/path/here' comment = app('Finder').items[path.replace('/', ':')].comment.get()

Better Random Password

An even better method of getting a random (ascii) password: $ head /dev/urandom | strings -n 5 | sed 'N;s/$//;s/\n//g;s/\n//g' | sed 'N;s/$//;s/\n//g' | head -n 1 (All on one line, naturally). I had to do the two seds to make it work properly. It would have been nicer if this combined all of the lines, and then I could just trim as many chars as I wanted, but this was tricky. The head -n 1 discards any lines other than the first.

Random Password

I needed a nice random password, something that is fairly strong. Enter /dev/urandom and md5: $ head /dev/urandom | md5 e98afcb4f093bafa0cc5f90f150df8b7 Obviously, that’s not the password I used. Problems with this method: if you don’t write it down, or save it somewhere, you will not be able to get it back. Second, it only uses a small subset of the ascii codeset – 0123456789abcdef. I’ve tried to come up with something that converts this to ascii, but I’m still working on it. You’d also likely want to ignore 8-bit values, as these can be extended characters. If you ever needed to type this in, it’s sometimes hard to do. The big advantage is that this is a totally random method, and you won’t get the same code twice.

MacOS Internet Sharing keeps stopping

I’ve borrowed a laptop from work, and a Wireless Access Point device, so now I can do stuff from my bedroom late at night, like I am this. However, just recently I have come across some sort of strange behaviour. Sometimes, but not all of the time, MacOS’s Internet Sharing feature seems to get turned off. Which means I need to get access to the machine and restart it. Not much fun when I’m all toasty warm in bed, and the Mac is in the cold, cold study. So, I’ve done a little bit of research. I might be able to restart it using: $ sudo /usr/libexec/InternetSharing I’ll try that next time it drops out… but I’d rather have a better fix.

Shell Calc

Whenever I need to do any calculations, I generally drop into python and do them from there. However, I came across a neat tip over on Mac Geekery: When You Need A Calculator. I’ve modified is ever so slightly so it goes into a .profile instead of a .bashrc:

1     function calc
2     {
3         awk "BEGIN {print $* ; }"
4     }

Sweet.