Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

20150523

Giving VirtualBox Guests Access to the Internet Without Exposing the Host's Network

I have a virtual machine running under VirtualBox that needs to be able to get updates from the Internet. Using VirtualBox's normal network interface methods (NAT or Bridging), the guest machines not only have access to the Internet, but also to all the interfaces on the host machine and their networks! Googling around for a solution didn't turn up anything useful, and VirtualBox seems reluctant to provide a Internet only option either.
 
After trying for about a day to mess with various iptables solutions and coming up empty handed, I decided to try a different approach to the problem. My solution is to create another “router” virtual machine and connect the main virtual machine through it to the rest of the network. All network traffic for the guest would go through an “Internal Network” connection to the router VM, and then the router would provide NAT, DHCP, and DNS services for the guests. This solution also has the benefit of providing multiple guest VMs with Internet-Only connections.
 

The router VM is very lightweight and doesn't require too much in the way of resources. I used Ubuntu Server 14.04.2 (32 bit), creating a virtual machine with 512MB of RAM and 10GB hard drive. (You could probably get away with less RAM and drive space, but I haven't played with trimming it down yet.) The secret sauce is in how the network adapters for these machine are configured. For the guest machine, you need to set up a single network adapter on an “Internal Network” (named vbx-router in this case). You can do this from VirtualBox GUI or the command line as follows:
vboxmanage modifyvm "guest-vm-name" --nic1 intnet --intnet1 vbx-router

The router VM will have two adapters, the first one bridged to the host's main network interface (typically eth0 on Linux hosts), and the second one using the same internal network we defined for the guest VM. The command line for this would look something like:
vboxmanage modifyvm "router-vm-name" --nic1 bridged --bridgeadapter1 eth0
vboxmanage modifyvm "router-vm-name" --nic2 intnet --intnet2 vbx-router

After installing the Ubuntu 14.04.2 x32 Server (you can use your favorite flavor of non-GUI Linux, your mileage may vary), make sure it is up-to-date (sudo apt-get update and sudo apt-get upgrade on Ubuntu/Debian). It's also probably a good idea to install OpenSSH Server, especially if your virtual machines are headless like mine. Next, it's time to install and configure the routing services. These instructions are based off a really useful blog post over at The Novian Blog.
 

Configure the Interfaces

Edit the /etc/network/interfaces file so it looks similar to this:

# The loopback network interface auto lo iface lo inet loopback # The WAN (bridged) interface auto eth0 iface eth0 inet dhcp # The LAN (internal) interface auto eth1 iface eth1 inet static address 10.0.2.1 netmask 255.255.255.0 network 10.0.2.0 broadcast 10.0.2.255

You can set up the WAN interface with a static IP if you'd like, but the LAN interface should be static so that guest VMs can always find it. The addresses for the LAN interface were chosen to be similar to the default NAT configuration provided by VirtualBox.
 

Install and configure DNSmasq

DNSmasq is a simple to setup DHCP server and DNS forwarder, install it with the command:
sudo apt-get install dnsmasq

Then add the following to the bottom of /etc/dnsmasq.conf:
interface=eth1
domain=home.teknynja.com
dhcp-range=10.0.2.10,10.0.2.99,12h

Of course you will want to change the domain to something suitable for your network.
 

Enable IP Forwarding

Un-comment the following line in /etc/sysctl.conf:
net.ipv4.ip_forward=1

Configure iptables

Create the file /etc/iptables.rules:
*nat
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT

*filter
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth0 -j DROP
COMMIT

*raw
-A PREROUTING -i eth1 -d 192.168.0.0/16 -j DROP
COMMIT

This configuration does the following:
  • Sets up NAT outbound on eth0
  • Allows all inbound localhost traffic
  • Allows inbound established connections
  • Allows SSH connections from WAN to our router
  • Drops anything else coming in from eth0
  • Drop packets coming from eth1 destined for host's local network(s)
Activate the rules (as a quick sanity check before rebooting!):
sudo iptables-restore < /etc/iptables.rules

Now try to ssh into the router and verify that you can connect. Once you verify that the rules are working, configure iptable rules to load on network startup. Add the following to /etc/network/interfaces after the line iface lo inet loopback:
pre-up iptables-restore < /etc/iptables.rules


 

Profit!

Reboot your router virtual machine to make sure it loads all your new configuration. Next double check your VirtualBox network configuration on the guest VM then go ahead start it. Check to make sure the guest picks up an IP address from the router VM, and proceed to test your guest's network. You should now be able to access the Internet, but be unable to access anything on your local network (including the host!)
 
Hopefully this will help you create an isolated guest with Internet access in your setup. I've been needing something like this for a while, and now that I've figured it out I felt like I needed to share. If you see anything wrong with this setup, or know how to make it more secure, please feel free to leave a comment.

Read More......

20150517

How to Remove the GUI from your Raspberry Pi

I was getting prepared to start another headless Raspberry Pi project (an IoT gateway) and reached for my old standby command line operating system, Minibian. I grabbed the latest version, copied the image to the memory card, and started setting things up. I ran into a problem when I tried to get the RaLink RT5370-based USB WiFi Adapter working - the kernel seemed to recognize the device, but I just couldn't get it working. After digging through the system logs it became apparent the firmware required by the adapter was not present in Minibian (Only later did I realize that I may have just needed to install a package to get the required firmware). After trying to get the WiFi adapter to work for a few hours, I gave up and switched to Raspbian. I was then able to get everything working (including the WiFi adapter), but was left with a GUI and it's associated bloat that I didn't really need, so I set about seeing what packages could be removed and still leave me with a fully functioning command-line based system.
 
Initially, I just did a search on the web and found a few different posts and conversations that dealt with removing the GUI and combined them to get things slimmed down quit a bit. After that, I started listing the installed packages and removing the ones that looked like they would not be needed. (It was at this point I noticed the firmware-ralink package that I could have probably installed on Minibian to get the WiFi adapter working there – maybe next time).
 
My first stop was a conversation on raspberrypi.stackexchange.com where it was suggested that you could rip out the X window system by the roots by simply removing ''libx11-.*''. That did remove a lot of packages from the system! Other blog posts like this one at Richard's Ramblings added to the list of packages to remove.
 
Finally, I used the dpkg --get-selections | grep -v deinstall command (thanks askubunut.com!) to list all the remaining packages on the Raspberry Pi and removed all the ones that look like I could do without. There were a few times when I removed too much and had to re-install a package or two, but eventually boiled it down to the following commands to convert a normal GUI Raspbian installation to a lean command-line only version (Be sure you don't have any important files or configuration on your system before doing this, and don't blame me if your mission critical Raspberry Pi application gets lost in the process!).  
A word of caution: One of the uninstalled packages took the /etc/network/interfaces file with it, so before stripping all these packages, you should make a copy somewhere else on the device and then restore it before rebooting your system, or you will have no networking available after rebooting!
 
sudo apt-get remove --auto-remove --purge libx11-.*
sudo apt-get remove --purge raspberrypi-artwork triggerhappy shared-mime-info gcc-4\.[0-7].*
sudo apt-get remove --purge gdb gdbserver penguinspuzzle samba-common omxplayer
sudo apt-get remove --purge alsa-.* build-essential gstreamer1.0-.* lxde-icon-theme
sudo apt-get remove --purge desktop-file-utils gnome-themes-standard-data menu menu-xdg
sudo apt-get autoremove
After all was said and done, I was able to reduce the size of the file system from 2.5GB down to just 800MB. Along with the size savings, there are also fewer programs running and fewer packages that need updating. Not to mention having less software on the system creates a smaller attack area for hackers to leverage.
 
So if you find that you need to remove the GUI from your Pi, hopefully this information will help you with your cleaning task. And of course, if you need something even smaller, there's always Minibian for a really stripped-down configuration.

Read More......

20140301

Raspberry Pi+Minibian: Adjusting the Locale and Time Zone

I really have enjoyed playing with the Raspberry Pi, but many of my projects don't require a GUI (for example OpenVPN and web servers). For projects like these, I usually install Minibian which is a great, small version of Raspbian with all the GUI goodness removed. It is a perfect starting point for my headless projects, except that out of the box, it comes setup with locale and timezones configured for Great Britian. This causes some strange characters to come up when typing on the keyboard, and the clock doesn't reflect my local time zone.

Fortunately, these issues are easy to address, and I will show you the steps I take to configure my system for my locale and time zone (us-EN & America/Los_Angeles). Just use your locale and time zone in the steps below to configure your system as desired.

  1. Install Minibian on your SD card following the provided instructions. Insert the card into your Raspberry Pi, power it up, and log in. (The default username/password is root/raspberry). You may also want to change the name of your system from the default "raspberrypi" by editing the /etc/hostname file.
  2. Change the keyboard locale. Run the following command:
    dpkg-reconfigure keyboard-configuration
    then
    • Set your "Keyboard model" to "Generic 105-key (Intl) PC".
    • Set the "Country of origin for the keyboard" and "Keyboard layout" both to "English (US).
    • Next for the "Key to function as AltGr" choose "The default for the keyboard layout".
    • For "Compose key" I chose "No compose key".
    • Finally, choose "No" for "Use Control+Alt+Backspace to terminate the X server".
    Once the command completes, reboot your Raspberry Pi to pickup the new keyboard layout.
  3. Now change the system local. Run the command
    dpkg-reconfigure locales
    and de-select "en_GB.UTF-8 UTF-8" and select "en_US.UTF-8 UTF-8", then set the default locale to "en_US.UTF-8" on the next screen.
  4. Edit the /etc/default/locale file and change/add the following lines:
    LANG=en_US.UTF-8
    LC_ALL=en_US.UTF-8
    LANGUAGE=en_US.UTF-8
    then log out and back in again to pick up the new locale.
  5. Finally, run
    dpkg-reconfigure tzdata
    and select "America", then "Los_Angeles" to set the local time zone for your system.
  6. Now that your system understands you a little better, it's probably a good time to update your system using
    apt-get update
    apt-get upgrade
    then reboot your system again.

Optional Tweaks


If you'd like to make your system a little more secure, you can enable sudo and disable the root login with the following steps:
  1. Install sudo:
    apt-get install sudo
  2. Create your new user. For example, to add the user "bob" run the command
    adduser bob
    and follow the prompts.
  3. Add your new user to the sudoer's list. Run visudo then add the following line (changing the username to the user you just added) after the root ALL=(ALL:ALL) ALL line:
    bob ALL=(ALL:ALL) ALL
  4. Now disable the root user with the command
    passwd -l root
    (note that is a lower-case L, not a one)
  5. Now log out of your root session and log in as your new user.
Finally, it's a good idea to change the SSH server keys because the ones that come with the image file make it easy to impersonate your system (since everybody has access to those keys):
sudo rm /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server

Now you should have a headless Raspberry Pi system that you can use for various server projects that is customized for your locale and timezone! If you have any questions or comments on this procedure, please feel free to leave a comment.

Read More......

20130609

Making kvm/qemu/libvirt Play Nice with PulseAudio on a Headless Ubuntu 12.04 Server

I've been running over a dozen virtual machines on my headless server for almost two years now, and for all that time I've always missed being able to hear the audio from those machines. I would occasionally try to figure out how to make audio work over VNC, but never could find a solution on the Internet. Finally last week I decided to at least get part-way there by getting the audio to play on the server's speaker port. The first step was pretty easy – installing PulseAudio on the server:

sudo apt-get install pulseaudio

Now from what I could gather on the Internet, it seems like I needed to run PulseAudio in system mode, despite all the warnings that it should probably not be run that way. I figured that since I don't usually have any logged in users on the system, it would just be better to have it running all the time. In order to do that, I edited the /etc/default/pulseaudio file, and changed the following settings to:

PULSEAUDIO_SYSTEM_START=1
DISALLOW_MODULE_LOADING=1

Then I added my user and the libvirt-qemu user to the pulse-access group:

sudo adduser myuser pulse-access
sudo adduser libvirt-qemu pulse-access

You'll need to log out and back in again for the new group to be picked up on your shell. Finally, I started the PulseAudio service:

sudo service pulseaudio start

Now a quick test to make sure the sound subsystem was working:

paplay test-sound.wav

In my case, I could barely hear the sound playing, so I did a pactl list sinks to figure out which sink was being used, then issued
pactl set-sink-volume 1 100%
pactl set-sink-mute 1 0
to set the volume level of sink 1 to the maximum and unmute it. Now I could hear the sound just fine!

The next hurdle was to get the sound from the virtual machines to play through PulseAudio. It turns out there are quite a few obstacles to achieving that goal. First off, libvirt automatically disables audio if you are using a VNC client! It turns out to be fairly simple to fix that though, simply edit /etc/libvirt/qemu.conf and change the following setting to:

vnc_allow_host_audio = 1

After restarting the libvirt daemon using sudo service libvirt-bin restart I could see in the syslog file that libvirt/kvm was trying to use the PulseAudio subsytem, but apparmor was blocking access to several key files/directories. I never did find a working answer by Googling, but I worked out the following settings for the /etc/apparmor.d/abstractions/libvirt-qemu file. I changed /{dev,run}/shm r, to /{dev,run}/shm rw, then added /{dev,run}/shm/pulse* rw, right after that line. Finally I added /var/lib/libvirt/.pulse-cookie rwk, (note the trailing commas on those lines!) then told apparmor to reload the configuration:

sudo invoke-rc.d apparmor reload

I fired off a Windows XP x32 guest, and was able to hear sound, but it was very distorted and choppy. The solution to that was to change the sound hardware in the virtual machine's configuration file from <sound model='ac97'> to <sound model='es1370'>. After that, I was getting perfect sound from my virtual machine!

Now for a few caveats – it seems that changing any of the PulseAudio configuration or restarting the service while the virtual machine is running can cause problems like the sound no longer working, all the way to the virtual machine's OS hanging up trying to play sounds. So once you started your virtual machine, leave things alone! I have also been working on trying to forward the sound over the network to my workstation, but so far I am having mixed results with that. Hopefully I'll have another post soon describing how to make that work.

And here is the usual warning that goes with tweaking your system like this: These instructions worked for me, but your mileage may vary. Also, I won't be responsible if any of this causes your machine to stop working or catch on fire – but this stuff should be pretty straight-forward and not cause any serious issues that can't be reversed. Hopefully my adventure will help you to enjoy hearing from your virtual machines. If you have any questions or corrections, please feel free to post them in the comments.

Read More......

20130527

Time-Lapse Video Capture From Network Cameras (Linux)

I have several network cameras watching the outside of my home, monitored by ZoneMinder. I have it set up so that when there is motion detected, it will record for several seconds and send me an email with stills of the incident. While this is nice and gives me a little peace-of-mind, I've always thought about having it record continuously. While it is easy enough to do in ZoneMinder, I didn't really want to use up that much storage recording video and then have to scroll through it to find anything interesting.

The other day I saw a blog post where someone was using a Raspberry Pi and a webcam to do some time-lapse photography, and that sparked an idea that seemed easy enough to do in an afternoon – I could come up with a Python script to grab images from the network cameras at fixed intervals, and write them to a video file in order to generate a time-lapse video!

The first step was to figure out how to build a video file a frame at a time using Python. I had played with the motion-jpeg (mjpeg) format in the past, which pretty much consists of jpeg images streamed one after the other in a file (sometimes with a boundary record between them). I discovered that I could simply capture and append jpeg images to a file and get a video file that could be read by a few video players and converters. Best of all, I could use a simple avconv (formerly ffmpeg) command to convert the mjpeg files to mp4, which is smaller and viewable by almost any player.

Next, I wanted to be able to time-stamp each image so that I could tell when the video was created. For this I stumbled across the Python Imaging Library (PIL) which supports several image formats, including jpeg. Using it, I was able to select a font and write a time-stamp on each image as it was captured before adding it to the mjpeg video file. If it isn't already installed on your system, you can install it using

sudo apt-get install python-imaging
for Debian-based systems or by using the appropriate package manager for your distro.

With all the pieces in place, I developed a little Python script that periodically grabs images from several network cameras and builds a separate mjpeg file for each of them:

talicam.py:
#!/usr/bin/python

# Number of seconds between frames:
LAPSE_TIME = 30

# Name of truetype font file to use for timestamps (should be a monospace font!)
FONT_FILENAME = "UbuntuMono-B.ttf"

# Format of timestamp on each frame
TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"

# Command to batch convert mjpeg to mp4 files:
#  for f in *.mjpeg; do echo $f ; avconv -r 30000/1001 -i "$f" "${f%mjpeg}mp4" 2>/dev/null ; done

import urllib
import sys, time, datetime
import StringIO
import Image, ImageDraw, ImageFont

class Camera:
    def __init__(self, name, url, filename):
        self.name = name
        self.url = url
        self.filename = filename
        
    def CaptureImage(self):
        camera = urllib.urlopen(self.url)
        image_buffer = StringIO.StringIO()
        image_buffer.write(camera.read())
        image_buffer.seek(0)
        image = Image.open(image_buffer)
        camera.close()
        return image
        
    def TimestampImage(self, image):
        draw_buffer = ImageDraw.Draw(image)
        font = ImageFont.truetype(FONT_FILENAME, 16)
        timestamp = datetime.datetime.now()
        stamptext = "{0} - {1}".format(timestamp.strftime(TIMESTAMP_FORMAT), self.name)
        draw_buffer.text((5, 5), stamptext, font=font)

    def SaveImage(self, image):
        with open(self.filename, "a+b") as video_file:
            image.save(video_file, "JPEG")
            video_file.flush()

    def Update(self):
        image = self.CaptureImage()
        self.TimestampImage(image)
        self.SaveImage(image)
        print("Captured image from {0} camera to {1}".format(self.name, self.filename))


if __name__ == "__main__":
    cameras = []
    cameras.append(Camera("porch", "http://username:password@10.17.42.172/SnapshotJPEG?Resolution=640x480&Quality=Clarity", "cam1.mjpeg"))
    cameras.append(Camera("driveway", "http://username:password@10.17.42.174/SnapshotJPEG?Resolution=640x480&Quality=Clarity", "cam2.mjpeg"))
    cameras.append(Camera("backyard", "http://username:password@10.17.42.173/SnapshotJPEG?Resolution=640x480&Quality=Clarity", "cam3.mjpeg"))
    cameras.append(Camera("sideyard", "http://10.17.42.176/image/jpeg.cgi", "cam4.mjpeg"))
    cameras.append(Camera("stairway", "http://10.17.42.175/image/jpeg.cgi", "cam5.mjpeg"))
    
    print("Capturing images from {0} cameras every {1} seconds...".format(len(cameras), LAPSE_TIME))
    
    try:
        while (True):
            for camera in cameras:
                camera.Update()
                
            time.sleep(LAPSE_TIME)
            
    except KeyboardInterrupt:
        print("\nExit requested, terminating normally")
        sys.exit(0)

Notice the URLs supplied in the Camera constructors. These are specific to each brand of camera, but you can usually find the format with a little Googling. In my program above, the first three cameras are Panasonic BL-C101A network cameras, the last two are a D-Link DCS-930L and a TrendNet TV-IP551W which both have very similar software and URLs.

The font file referenced above needs to be located in the same directory as the Python script, and for best results should be a mono-space font. I just grabbed the Ubuntu Monospace Bold TrueType font file for use here, but you could use anything you like.

You will probably want to launch this as a background task so that it can run for extended periods of time. I have it running on the same server that runs my ZoneMinder setup, so it can run 24-7 collecting time-lapse video. I also wrote a quick little script file that iterates the mjpeg files it finds and converts them to mp4 for easier viewing and archiving:

mjpeg2mp4:
#!/bin/bash

echo "Removing old files..."
rm -fv *.mp4

echo "Converting files to mp4..."
for f in *.mjpeg ; do
    t=${f%mjpeg}mp4
    echo "  Converting $f to $t"
    avconv -r 30000/1001 -i "$f" -q 5 "$t" 2>/dev/null
done

echo "Done!"

I had a lot of fun learning a few new tricks while working on this, and hopefully you can use it as a starting point for your own time-lapse adventure. If you find this post useful, or have questions about how it works, please leave a comment below.

Read More......

20110827

Hacking WebRunner to work with Firefox 6.0

I have come to depend on Salsita Software's WebRunner extension for Firefox that let's me create “applications” out of web sites. It comes in especially handy when I want to be logged in with multiple identities on the same web site, as well has keeping an always open window on my Zoneminder cameras.

When Firefox 6.0 was pushed out in Ubuntu, I was quite dismayed to find that when it checked add-ons and extensions for compatibility, WebRunner was not compatible, and furthermore, an updated version was not available. I waited for around two weeks for Salsita to update their software, but so far there's been nothing. So I dug around in the .xpi file and came up with this hack to make the current version work with Firefox 6. These instructions are for Ubuntu/Linux (since that is all I have running now), but the changes should be very similar for Windows as well.

First download (but don't install/run) the latest .xpi file from here. Then open the file with an archive manager (.xpi files are really just jar/zip files) and edit the file install.rdf, changing the value of /RDF/Description/version from 5.0 to 5.1, and the value of /RDF/targetApplication/maxVersion from 5.* to 6.*. Next, edit the file stub/application.ini, changing the value for MaxVersion from 5.0.* to 6.0.*. You may want to rename the .xpi file at this point to make it easier to keep track of it.

Now update to Firefox 6.0 (if you haven't done so already) and remove the old WebRunner 5.0 extension, in Tools|Add-ons on the Extensions tab. Close that dialog, and go to File|Open File... in Firefox and select your modified .xpi file. It should install without complaint, indicating it is version 5.1 (hopefully Salsita will version their next release higher than this).

At this point, you can either re-create your web application shortcuts, or hack the existing ones to work with the updated extension. To fix the current shortcuts and applications, modify the command for the shortcuts to point to firefox-6.0 instead of firefox-5.0. Then for each application in your ~/.webapps directory, edit the appname@webrunner/stub/application.ini file and change MaxVersion from 5.0.* to 6.0.* and change GRE_HOME to /usr/lib/firefox-6.0. Now try to launch your web application shortcuts and you should be good-to-go!

As with most hacks, I make no guarantees that this won't in some way hose your Firefox installation or your entire computer, so attempt this at your own risk! On the other hand, if you are like me and depend on the excellent WebRunner extension, this hack is a quick way to get it back in Firefox 6. Make sure to leave comments if you have tried this under Windows and get it to work.

Read More......

20100307

std::string and sprintf

Amongst the many projects I am currently juggling, one of them involves developing some C++ code for an embedded Linux project. I've just hit an instance where I'd like to be able to use “printf” style formatting using std::string instances, but it can be pretty clumsy – I need to allocate buffer space for sprintf, invoke the function, and package up the result into another string.

I did a quick search on the Internet and found many others looking for the same thing: “Is there a way I can use sprintf in c++ using std:strings?” And invariably the answers were either


  • “No”

  • “Use std::ostringstream and c++'s built-in manipulators”

  • “Use boost::format

And they are all right!

It turns out that you can't safely use the *printf style variable argument lists with C++, as only POD (Plain Old Data) types can be passed in the list. Attempting to pass most other types will result in a segmentation fault at run time. The official C++ way is to use ostringstream and the usual stream manipulators to format parameters, but for me, that make's writing tests more difficult because I need to “build” the expected streams exactly the same way in my test code. The final method could work for me, except that this is an embedded project and I am trying to keep the number of libraries referenced to a minimum, since I need to build and include them on my target Linux system.

So my solution was to accept the limitations of the printf function and write a wrapper function that hides the buffer setup and string creation:

#include <string>
#include <stdarg.h>
#include <stdio.h>

string FormatString(const string& format, ...) {
char buffer[1024];

va_list arglist;
va_start(arglist, format);
int length = vsnprintf(buffer, sizeof(buffer), format.c_str(), arglist);
va_end(arglist);

return string(buffer, length);
}



I've tucked this away in a nested namespace so I can invoke it easily when needed. Now when I need formatted text I can just supply a c string or std::string format and my parameters, and get back a nice std::string instance in return. But there's a catch! I can't pass in a std::string as a parameter because the old-school c variable argument list can't handle objects. If I try to do that, I will get a “warning: cannot pass objects of non-POD type 'struct std::string' through '...'; call will abort at runtime” warning and a segmentation fault at runtime. The work around (at least for std::string objects) is to invoke the c_str() method on the string parameter instance. So for example

    string argument = "a string instance";
string result = FormatString("I can format a %s parameter!", argument.c_str());


allows me to supply std::string arguments as well. The c_str() function returns a pointer to a temporary buffer containing a c style string version of the string object's value.

So now I have my template style formatting and I can move on with my project. This project is my first foray into any substantial C++ programming, so if you seen any glaring problems or know a better solution, or if this little tip helped you too, please let me know by leaving a comment.

Read More......

20091006

MonoDevelop Custom Color Schemes

I have been playing with MonoDevelop 2.0 on Ubuntu on and off for a while now, but one of the things I find most annoying (other than not having ReSharper) is there is no easy way to modify the colors used for syntax highlighting. Sure, it has several pre-defined schemes you can choose from (Using Edit | Prefrences > Text Editor > Syntax Highlighting), but changing individual syntax element colors using the GUI is not possible.


The reason I find this issue annoying is that I like to have comments and strings really stand out – in our shop we avoid comments as much as possible, and string constants are kept to a minimum, so I like to be able to see them easily in the code. A few years ago, I started using “highlighter” background colors for comments and strings, and have become quite attached to them ever since.


After many attempts to find a solution on the web, I finally found all the pieces I needed to make it happen. The basic problem is that although MonoDevelop allows you to add new color schemes, the format of the scheme file is not well documented, and there are a few tricks you need to know to make it work correctly. The existing schemes are embedded resources and not stand alone files, so they can't be easily viewed for reference. Finally, I discovered this Ubuntu Forum thread that helped me find the solution. The first piece of the puzzle was discovering the color scheme XML source files in MonoDevelop's SVN tree. Now I had some samples to go by. Another useful tidbit from that thread was that the file name must end in "Style.xml" in order to work correctly. I did not actually verify that this was required, but I did it just to be safe. The rest came from a MonoDevelop Developer's Article page I stumbled across shortly thereafter. One of the important things mentioned on that page is that you need to put the color scheme XML file in the ~/.config/syntaxmodes directory (although in my Ubuntu installation it is actually ~/.config/MonoDevelop/syntaxmodes). Now I had everything I needed to start tweaking colors!

The first thing I did was download the VisualStudioStyle.xml file and renamed it to TeknynjaStyle.xml. Next I edited the file to change the name and _description attributes of the EditorStyle tag so they would not clash with the existing styles in the GUI. Finally, using the information from the MonoDevelop article and the existing examples, I modified the colors for comments and strings to get the highlighting I was looking for:

   <Style name="comment" color="black" bgColor="#ffff80"/>
<Style name="comment.doc" color="black" bgColor="#ff8040"/>
<Style name="comment.tag.doc" color="black" bgColor="#ff8040"/>

<Style name="text.preprocessor" color="purple"/>
<Style name="text.markup" color="skyblue"/>

<Style name="constant" color="black"/>
<Style name="constant.language" color="keyword-blue"/>

<Style name="string" color="black" bgColor="#80ff80"/>
<Style name="string.single" color="black" bgColor="#80ff80"/>
<Style name="string.double" color="black" bgColor="#80ff80"/>
<Style name="string.other" color="black" bgColor="#80ff80"/>

<Style name="keyword" color="keyword-blue">
<Style name="type" color="#004080"/>
</Style>

I found the "bgColor" attribute by looking in one of the other color scheme files. Then I copied my customized color scheme file to ~/.config/MonoDevelop/syntaxmodes, restarted MonoDevelop, and selected my color scheme. I was able to tweak the colors by editing the XML file and restarting MonoDevelop until I achieved the scheme I was looking for. Finally I had the highlighting I was used to in Visual Studio, and along with modifying some of my commonly used key bindings, I was able to make MonoDevelop feel a little more like "home".

Read More......

20080928

Ubuntu Photo Frame


About two years ago I converted an old laptop into a photo frame for the living room. There are plenty of examples of how to do this floating around on the web these days, so I am not going to cover that here. What I am going to talk about are the software aspects of this project, and my recent upgrade of my photo frame.

The frame had been working fine for almost two years, but a few months ago I upgraded my WiFi network at the house to WPA (finally), but that meant that I could no longer transfer files to the frame because the WiFi card I was using in it only supported WEP. Shortly after that, the frame started acting strangely, turning itself off about once a day, then finally not booting at all with the infamous “missing file” messages you get when Windows can't read the hard drive correctly.

The original software setup for this project was Windows 2000 with a small .NET application I wrote to scan a directory and display pictures from it. When it was time to display the next photo, the program would scan the directory and pick a new picture at random to display. The laptop hardware did not have enough “horsepower” to handle any kind of transitions or fades between photos, so the program just displayed the next photo on the screen without any transitions.

I brought the frame back to my cave, where I confirmed that the hard drive had indeed given out. I ordered a SYBA SY-IDE2CF-NB25 Ultra IDE to Compact Flash Adapter from StarSurplus, and with a 4GB Compact Flash card I had laying around, I now had a solid state hard drive for the frame. I also ordered a EDIMAX EW-7108PCg 802.11g/b Wireless LAN PC Card from NewEgg to allow WiFi access to the frame again. I selected this card because it is well supported under Linux and it is very inexpensive. Now that I had all the hardware ready, time to re-install the software.

I wanted to use Ubuntu for this project, because I am familiar with it, and this would give me an opportunity to learn about doing a very minimal installation. My goal was to use as little space on the flash drive as possible for the OS and supporting programs to leave room for photos. After a few practice runs setting up the system and trying different programs, I came up with the following recipe.

First, I installed Ubuntu Server, with the OpenSSH and Samba options. The server edition of Ubuntu doesn't install any kind of GUI (just a command prompt) and none of the heavy applications like OpenOffice, Evolution, etc. Then I got the Wifi card working (it wasn't detected during setup) and performed an upgrade to make sure I had the latest security patches. I setup Samba to allow access to the folder containing the pictures to be displayed. Next I apt-get installed xorg, dnotify, and feh. feh is a small, lightweight image display program for X. While playing around with different configurations, I discovered that even under Ubuntu, this laptop just didn't have what it takes to display transitions between photos, and so feh fit the bill almost perfectly.

I tweaked the xorg.conf file to prevent it from blanking the screen (I think it defaults to blank after 10 minutes), copied some photos to the frame, and fired off feh using xinit. And my photo slide show started up! The only problem with feh is that it only reads the files in the directory when it starts up, so if I add pictures to the directory later, I would have to restart the program in order for them to be shown. So I created the following script using dnotify to restart the program whenever any files in the folder have changed.


#!/bin/bash
export HOME=/home/teknynja
while true; do
killall -q feh
sleep 1
xinit /usr/bin/feh -rzFZD180 --hide-pointer /home/teknynja/Pictures &
dnotify -MCDRro /home/teknynja/Pictures
done

I made the script executable, and added a line to invoke the script from inside /etc/rc.local so that it would run when the system started up. After a couple of days of testing in the cave, I put everything back together and it is now back in the living room, displaying our family photos once again. It also has the added bonus of being completely silent, due to the solid state hard drive. The total space budget on the flash drive was 645MB for the OS and supporting programs, leaving around 3GB for photos, which is more than enough for now.

Once again I warn the readers that I still have a lot to learn about Linux, so any constructive comments are appreciated. If you have any questions or would like more details about this project, feel free to leave a comment and I will try to help you if I can.

Read More......

20080908

Obscure Ubuntu Tip: CRON User account has expired

No, I haven't forgotten that I have a blog. I've just been keeping busy with a lot going on at work, and a backlog of “projects” at home after finishing up the kitchen project. Some of those projects have involved getting down-and-dirty with Ubuntu, and I thought I would share a quick tip I discovered yesterday.

I was looking through the system log (/var/log/syslog) on one of my servers and I noticed it was full of “CRON[xxxx]: User account has expired” messages. A little searching on the web pointed to the fact that the root account had been locked. While setting up this server, I had followed some instructions I found on the web that required me to unlock the root account, then re-lock it when I was done with the

sudo passwd -l root
command. Locking an account this way also causes the password to be expired, one of the results of which is the above mentioned log entries. Most of the solutions I found on the web involved either unlocking the root again and giving it a long, random password, or manually editing the password files. I think I've found the correct way to fix this though, by using the
sudo chage -E-1 root
command, which sets the root's password to never expire. (Note that the -1 is negative one, not dash L). After using the above command, the system log showed normal CRON log entries, and the root account remained locked.

I hope someone else will find this information to be of use. That's it for my very obscure Ubuntu tip. Join me again soon for another exciting post. I actually have a good sized list of topics to cover on the blog, so hopefully things will settle down and you will hear more from me soon. Thanks for stopping by!

Read More......

20080426

Ubuntu 8.04 Hardy Heron Synergy Client Setup

In the Teknynja cave I have a MS Windows XP box with two monitors (my main development system) and a Ubuntu box with one monitor (my Internet offload system). I use Synergy to control the Ubuntu system using XP's mouse and keyboard. Since the Ubuntu box doesn't have a keyboard or mouse connected to it, a little hacking is required to get the Synergy client running before the login screen. I've been doing this with my Ubuntu 7.04 system for a while, and now that I am setting up a replacement Ubuntu 8.04 system, I thought I would document the Synergy client setup for future reference. It should be noted that I installed Ubuntu Hardy Heron from the Alternate CD, but that should not make a difference for this procedure. I also assume that you already have the Synergy keyboard/mouse server configured and running somewhere on your network.

First, install Synergy on the Ubuntu system using:

sudo apt-get install synergy

Then edit the gdm initialization file:

sudo nano /etc/gdm/Init/Default

and add the following lines just before the “sysresources=/etc/X11/Xresources” line

/usr/bin/killall synergyc
sleep 1
/usr/bin/synergyc xxx.xxx.xxx.xxx

where xxx.xxx.xxx.xxx is the IP address of your server machine.

Now edit the gdm pre-session file:

sudo nano /etc/gdm/PreSession/Default

and and the following line just before the “XSETROOT='gdmwhich xsetroot'” line

/usr/bin/synergyc xxx.xxx.xxx.xxx

Make sure the Synergy server is configured and running on your keyboard/mouse system, and reboot the Ubuntu system. You should now be able to move the mouse over to the Ubuntu screen and login normally.


Note that I still consider myself a Ubuntu/Linux noob, and so any improvements/comments/suggestions you have about this post are greatly appreciated. Ymmv. Most of the help I needed setting up this configuration came from the Ubuntu Synergy How To page.

Read More......

20080407

Waiting for Heron


The countdown to the release of Ubuntu Hardy Heron is on here. I've had a couple of ex-windows boxes sitting around for the last couple of months, hard drives all cleaned off in preparation. One of them used to be my main work machine at home, a 2.5Ghz P4 w/3G RAM, and the other was my home theater box running a 2.4Ghz hyper threading CPU with 2G of RAM. And while the HTPC's replacement system, a 2.6Ghz Dual Core is now happily running MythTV over Ubuntu, the Quad-Core workstation replacement is still booting Windows XP (as my bread and butter is .NET development).

I've been playing around with Ubuntu for a little over a year now, and although I still consider myself a Linux noob, I feel pretty comfortable working and playing on those machines. I have an older Pentium II machine sitting under my desk next to my workstation running Ubuntu with its monitor sitting next to my Window's two monitors, sharing the keyboard and mouse via Synergy – so I have quick and easy access to a Ubuntu box for experimentation. I also have a headless Ubuntu box in the garage streaming a distant radio station, so I can listen to it anywhere I have net access – at home, at work (about an hour commute from my house) or on the road via my MDA Smartphone. I also have a very old laptop with Ubuntu on it, but I hardly use it since it is so underpowered anyway.

So when Hardy Heron is released on 24-Apr-2008, I'll be loading it onto my old workstation and replacing the Ubuntu box under my desk, and playing with all the latest wiz-bang Compiz graphics. As for the old HTPC box, I will probably do a case transplant to move the hardware into something a little less cramped, load Ubuntu on it, and set it up for my wife, who is currently running on an old Win2K box. And what I am going to do with the two old boxes I free up? I'm not sure right now, but I'm almost positive they will be running Ubuntu as well!

Oh, yeah – welcome to Teknynja, and if you have any questions about the projects going on around here, please feel free to ask!

Read More......
 
Template design by Amanda @ Blogger Buster