Friday, May 13, 2005

Cool *nix based backup tool - written in Python

rdiff-backup - A remote incremental backup of all your files could be as easy as

"rdiff-backup / host.net::/target-dir"

A friend turned me on to this tool, seems to have nice features compression, runs over ssh, you can backup between 2 remote machines, incremental back etc... A list of its features can be found here:

rdiff-backup features

Looks like someone tried to use it on windows in cygwin to a limited effect. rdiff-backup seems to work as billed on linux.

Friday, May 06, 2005

Inserting data into the parent process

On Linux, and other UNIX-like systems that support it, you can make an ioctl call to insert data into your standard input file. That's pretty neat in an of itself, but it gets better: in most cases, you share the standard input of your parent process. What that means is that you can insert data into that file, and then terminate... and the parent process will read those data as user input.

The following Python snippet will, when run from a command shell, cause that shell to print a file listing of the current directory.

#! /usr/bin/env python
from fcntl import ioctl

TIOCSTI = 0x5412

ioctl(1, TIOCSTI, 'l')
ioctl(1, TIOCSTI, 's')
ioctl(1, TIOCSTI, '\n')

This trick has security implications, and is one reason why programs that run as root should never pass their open file handles on to their children.

Wednesday, May 04, 2005

Manipulating Windows registry values

Here is a small class that connects to the Windows registry and creates sub-keys and/or values for a given registry key. I used this functionality very recently to add a directory to the PATH environment variable by modifying the Environment\Path registry value.

Update 06/08/05: When modifying the 'Path' registry value, we need to set a value type of REG_EXPAND_SZ and not REG_SZ, otherwise variables like %SystemRoot% will not get correctly expanded by the command prompt interpreter and the WINDOWS\system32 directory will not be found. I added a value_type parameter defaulting to REG_SZ to the set_value method.
import _winreg
class WinRegistry:

def __init__(self, reg=_winreg.HKEY_LOCAL_MACHINE,
key=r"System\CurrentControlSet\Control\Session Manager\Environment"):
self.reg = _winreg.ConnectRegistry(None, reg)
self.key = key

def create_subkey(self, subkey):
key = self.key + "\\" + subkey
_winreg.CreateKey(self.reg, key)

def delete_subkey(self, subkey):
key = self.key + "\\" + subkey
_winreg.DeleteKey(self.reg, key)

def set_value(self, value_name="", value="", subkey=None, value_type=_winreg.REG_SZ):
key = self.key
if subkey:
key += "\\" + subkey
k = _winreg.OpenKey(self.reg, key, 0, _winreg.KEY_WRITE)
_winreg.SetValueEx(k, value_name, 0, value_type, value)
_winreg.CloseKey(k)

def get_value(self, value_name="", subkey=None):
key = self.key
if subkey:
key += "\\" + subkey
k = _winreg.OpenKey(self.reg, key)
value = _winreg.QueryValueEx(k, value_name)[0]
_winreg.CloseKey(k)
return value

def delete_value(self, value_name="", subkey=None):
key = self.key
if subkey:
key += "\\" + subkey
k = _winreg.OpenKey(self.reg, key, 0, _winreg.KEY_WRITE)
_winreg.DeleteValue(k, value_name)
_winreg.CloseKey(k)

if __name__ == '__main__':
wr = WinRegistry()

# Add ApplicationPath1 value_name to the Environment key
value_name="ApplicationPath1"
value="C:\\agent1\\agent.bat"
wr.set_value(value_name, value, value_type=_winreg.REG_EXPAND_SZ)
value = wr.get_value(value_name)
print "Created value_name %s with value %s" % (value_name, value)
# Now delete value_name
print "Now deleting", value_name
wr.delete_value(value_name)

# Create subkey Environment\EnvTest1 and add ApplicationPath2 value_name to it
subkey = "EnvTest1"
value_name="ApplicationPath2"
value="C:\\agent2\\agent.bat"
wr.create_subkey(subkey)
print "Created subkey", subkey
wr.set_value(value_name, value, subkey)
value = wr.get_value(value_name, subkey)
print "Created value_name %s with value %s" % (value_name, value)
# Now delete subkey
print "Now deleting", subkey
wr.delete_subkey(subkey)