Friday, June 14, 2024

The non-traditional start of my software engineering career

Unlike most software engineers, I started my career as a field engineer responsible for maintaining those large mainframe computers like the ones you see in movies.  You know the type with the line of tape drives whose reels keep spinning back and forth.  I got that job by attending the last full time field engineering class taught entirely by live instructors at the Arlington campus of Control Data Institute in 1976.  It was a 6 month full time program which taught electronics repair, debugging, and machine language programming.  They delved into topics such as optimizing Boolean logic which we then implemented by wiring together small boards each of which contained a single Boolean gate made up of discrete components such as transistors.  You haven't lived until you've built an adder circuit this way.  One of the big attractions was Control Data consistently managed to find jobs for more than 90% of their graduates from each class.  For the class which followed mine, they started using an early version of a computerized training system called PLATO for part of the training and eventually switched entirely to computer-based instruction.

In 1977, I completed my course and got hired as a field engineer by Honeywell Information Systems with the responsibility for maintaining their Level 6000 and 6600 series mainframes.  Much of the time I worked on peripheral equipment such as disk drives, tape drives, and line printers.  It's a sad fact of life that machinery with moving parts breaks down a lot more often than purely electronic equipment does.  Fixing mechanical problems is a necessary part of the job for field engineers but it's not always interesting and it often means getting covered in printer ink or grease.

My favorite part of the job was the more difficult debugging required when a computer fails to boot or when one crashes.  When the computer itself had problems, I occasionally had to troubleshoot the CPU the way the field engineer in the picture below is doing. 

The CPU for Honeywell's 6000 series of mainframes contained about 80 logic boards, each of which measured about 12" square and contained over 100 integrated circuits.  For the most difficult problems, we sometimes had to put the boards on board extenders similar to the one in the picture above which provided access for easier debugging using an oscilloscope to trace signals from board to board within the CPU.  For me, the best part of those mainframe computers was the large maintenance panels they had.  From that panel I could stop the CPU to examine the contents of registers, single step the CPU to see how it behaved while executing a section of software, and insert breakpoints to automatically stop on certain conditions.  That was when I was infected by the love of programming.  I'd get 2+ hour windows for preventive maintenance and if I rushed through running the system diagnostics, I'd have time left over to enter machine language programs on those maintenance panels.  Seeing the lights on the panel blink in ways I expected was a thrill.  I spent 5 years working at Honeywell but ultimately left because I was frustrated by the obstacles they presented to employees who want to make the switch from hardware to software.

My second job was with a small company called Atex which used DEC PDP-11 minicomputers to run publishing software used by magazines and newspapers.  For a while I was the onsite field engineer at USA Today and helped install the 12 PDP-11 minicomputers they used when they launched.  Most of my work was maintaining the 200+ terminals used by newspaper staff.  The terminals were simple but company policies declared the ORU (optimal repairable unit) to be the logic board which time consuming to replace.  So I started saving the chips which commonly caused failures from all of the defective boards I sent back to be repaired and I learned which chip to replace for various symptoms.  A vertical line across the screen meant the horizontal deflection chip was likely bad.  That allowed me to reduce my time to repair 45 minutes equired to replace the logic board to about 5 minutes to pop a new chip into a socket.  The time savings left me ample time to write machine language programs I could try during preventive maintenance windows.

Since the PDP was a smaller computer, its maintenance panel was much simpler (see below) than the one used by mainframes.  The CPU's instruction set was much simpler as well.  Maintaining minicomputers proved much less challenging than working on mainframes was.  Their CPUs only had a couple boards and instead of doing chip level repairs, we just replaced the bad board.  Frankly, I found the job a bit boring.  After a mishap where a minicomputer fell on top of me (which is a story for another time), I decided to make the switch from computer hardware to software. 


What I discovered at my first software job was thanks to my unorthodox introduction to programming, I had a much better understanding of low level programming than most of my colleagues did.  I also appreciated that as a software engineer, I was able to write assembly language programs rather then entering instructions as machine language which is just a group of numbers.  Writing assembly language was much less labor intensive.  The instruction "LDA" (load the accumulator register) was easier to remember than the fact that a 235 was the CPU's "op code" for a LDA instruction.   I also didn't have to manually calculate the jump offsets between instructions.  Yes sir, assembly language programming was much easier than what I was used to doing.

At GE, which was my 4th job, I wrote code for Honeywell 4500 series computers.  These were process control systems with a 24 bit CPU which had been modified for use in GE's packet switched network.  The 4500 was yet another another machine with a front maintenance panel.  Most of the code we wrote was in assembly language but the assembler wasn't very sophisticated and it wouldn't give a proper warning when a jump location was too far away.  What could happen was the jump offset might get large enough that it would set the top bit of the offset field, changing the jump direction from forward in memory to backward which caused unpredictable behavior.  I could catch these errors pretty quickly because the assembly listings from our programs also showed the machine language instructions one one side.  In the machine language column the direction of the jump offset was obvious to people who understood the instruction set.  Eventually I was put on a project to upgrade the network nodes to more modern hardware.  I was sent off to be trained on the new machines where I discovered that my management had completely ignored the class prerequisites of knowledge of the C programming language, much to the instructor's chagrin.  So I was forced to learn C during a several week course where I was expected to already have expertise in C and was also learning about the equipment's API.  It was hard until I finally realized that C is really just a portable assembly language.  After that, C became my favorite programming language and remains a favorite to this day.

Eventually I joined Sprint International where I was responsible for developing software for the equipment used in their packet switched network.  It was at Spring that I became obsessed with Unix because I had a Sun 3/80 workstation on my desk.  To this day, the Sun remains my idea of the ideal development environment.  It was also there where I first used a Motorola 680x0 CPU which features my favorite instruction set of any CPU.  One thing I found frustrating was Sun's version of vi (a visual editor) had restrictions on the width of a window and the overall size of the files which could be edited.  My machine language skills allowed me to patch my workstation's copy of vi to expand those restrictions to values I found easier to live with.

The vast majority of my career has been spent writing system software (operating system, device drivers, bootloaders, etc) or firmware.  The line between system software and firmware is sometimes hard to detect.  It can range from simple control loops which monitor and control hardware to what it has become today, hardware specific drivers on any one of multiple embedded operating systems, up to and including Linux.  Regardless of the platform I'm working on, the ability to decode machine language remains a valuable tool for me.  Since my firmware jobs often involve custom hardware, knowing how to read schematics has proved an essential skill as well.



Sunday, February 04, 2024

Making changes to your development setup easier

As I'm occasionally assigned new projects at work and as those projects progress, I find the need to update my development environment on a regular basis.  Having the ability to customize my setup allows me to be more productive.

To that end, I have defined a few bash aliases which help make this process easier for me.  These aliases are defined in my ~/.bash_aliases file.

#  config bash
alias   cfgb='gvim ~/.bash_aliases'
# config vim
alias   cfgv='gvim ~/.vimrc'
# source my bash aliases to pick up any new changes
alias   redot='source /home/rod/.bash_aliases'

You'll notice that I have an alias to make changes to my vim setup.  It makes sense to also have a vim macro to read any new configuration settings or vim macros.  This macro is defined in my ~/.vimrc file.

" source .vimrc ro pick up any new macros
map \.  :source /home/rod/.vimrc^M

Friday, December 29, 2023

Default apps for 2023

Lately, I've seen a lot of the "what apps am I using" type posts, apparently prompted by a podcast episode.  You can see a collection of what a number of people are using here.  I find these interesting as they're a good way to discover new apps which I hadn't been aware of previously.  These are the apps I use for my iPhone, Mac, and Raspberry Pi at home as well as the Linux and Windows machines I use at work.


  • Mail Client: Apple Mail, Outlook at work (barely tolerable but dictated by the IT team)
  • Notes: Apple Notes for shared notes, Editorial for notes I don't want on the cloud (such as those containing sensitive information such as birthdays)
  • Chat: iMessage
  • Camera: Apple Camera, Night Capture for evening sky photos
  • Photo Management: manual sync into directories on my Mac
  • Photo Editing: Preview on Mac, IrfanView on Windows
  • Calendar: Google Calendar - I like it for its ability to do custom repeats and for ease of having more than 2 notification reminders
  • Browser: On Macs I use Safari for lightweight browsing for its ease of sharing bookmarks with mobile devices, Firefox for general browsing because it has a richer collection of security plugins.  At work I use Chrome (barely tolerable but dictated by IT).
  • Backup: ChronoSync
  • Read It Later: Instapaper
  • RSS: Inoreader (web and app)
  • News: RSS feeds from news sites which lets me keep up with events without being distracted by things I'm not interested in such as sports
  • Podcasts: Overcast (great performance and the best UI of any app on my phone, bar none)
  • Books: Kindle, Audible, Libby, Hoopla
  • Database: Tap Forms (good sync between mobile and Mac)
  • Personal Finance: GNUcash
  • Password Management: 1Password - with 600+ non-trivial passwords to remember, this is a must
  • Music - Apple Music, Remote app to control desktop from my phone
  • Editing (code and general) - MacVim on Mac, GVim on work machines (Windows and Linux)
  • X Servers - XQuartz on Mac, VcXsrv on Windows
  • SCP client - WinSCP on Windows, scp from the shell on Linux/Mac machines
  • Terminal emulation - putty on Windows and Linux machines

Monday, November 20, 2023

We lost another dog to cancer

About a month after we lost our dog Bandit to osteosarcoma in March, we adopted a sweet female pit bull mix named Greta.  The jump from an 84 pound Lab, Shepherd, Husky, Pit mix who was strong enough to be considered a force of nature to a 49 pound pit bull mix made Greta seem petite.

Her happy personality was on display from the moment we picked her from the animal shelter.  She happily cuddled in my wife's lap for the 30 minute ride home.


She had had a rough early life, having been bred at least twice by the age of 2, followed by being abandoned in a fenced outdoor holding pen at a shelter in West Virginia.  Luckily for Greta and for us, she was transferred to the Loudoun County Animal Shelter which is where my wife discovered her.

Despite having shorter legs than Bandit did, Greta loved accompanying my wife on 2-3 mile walks once or twice a day.  She found people much more interesting than other dogs or toys and had a number of friends in the neighborhood.

Bandit had always wanted to be a lap dog but Greta was actually small enough for that to be a regular occurrence.  It's hard to tell whether she enjoyed it more or whether we did.  She was extremely affectionate.


 

In early September, we noticed some swelling on her neck, so my wife took her to the vet.  To the vet's surprise, it was not an infection but instead turned out to be lymphoma and a fairly advanced stage at that.  Apparently that's rare in a dog so young.  She was prescribed steroids which did a wonderful if somewhat temporary job of reducing the swelling.  It was lovely having an extra 6 weeks of time with her where she was relatively symptom free.

Unfortunately once the final dose was done, her swelling came back with a vengeance.  It quickly advanced from being an uncomfortable nuisance for her to starting to obstruct her breathing.  I'll never forget the look in her eyes which seemed to question why this was happening to her.


She was sweet and loving to the end, despite all she was going through.  We'll always miss her even though she was only with us for 7 short months.


Thursday, October 05, 2023

Tim Sullivan's The Teacher has left me wanting more

 One of my favorite authors, Tim Sullivan, mentioned in his latest newsletter, that fans could sign up to read an advance excerpt from his upcoming book, "The Teacher".  I couldn't resist the offer because I'm addicted to his excellent mystery novels which focus on Detective Sergeant George Cross.  Plus the opportunity to get a headstart on the next installment was too much to resist.  

DS Cross differs from most of his colleagues by being on the autism spectrum which gives him an incredibly focused approach to investigating crimes as well as a unique way of interacting with other people.  Sullivan's writing skill makes Cross a compelling and sympathetic figure.  The mysteries are well plotted and peopled with a believable cast of characters.

So how did I enjoy this latest book in the adventures of DS Cross?  I loved it!  I can't wait for the book to be released so I read the rest of it and find out what happens next.

Thursday, September 28, 2023

Scalzi's latest book, Starter Villain, is great fun

I finished John Scalzi's latest book, Starter Villain, yesterday.  After careful thought, I rated this book highly both because of the eagerness with which I anticipated it and the sheer joy it brought me while reading it. I listened to the audiobook version narrated by Wil Wheaton who invitably enhances SciFi or books aimed at those of us with geeky interests. Starter Villain is filled with Scalzi's characteristic humor, entertaining plotting, and a fair amount of topics to contemplate once the book is finished. In the end, I rated it this way because I'm still smiling having finished it meanwhile anticipating his next book.

Sunday, April 30, 2023

Cory Doctorow's new book is really good

I shouldn't be surprised about how good Cory Doctorow's new book, Red Team Blues, is.  I've been a fan of his books for about 20 years.  His books invariably involve new trends in technology and their possible consequences.  Cory definitely has the technical chops to write convincingly about emerging technologies.  He's an activist and has been involved with the EFF (Electronic Freedom Foundation) for many years.  Cory also has a frequently updated blog called Pluralistic which features an interesting article and lots of links, which often involve technology and its unintended consequences or occasional intentional misuses.

Red Team Blues follows the adventures of a forensic accountant (which apparently can be a much more interesting profession than the position title would imply) named Marty Hench.  Hench specializes in the cybersecurity and accounting involved with digitally accessed assets such as cryptocurrencies.  In Doctorow's capable hands this premise becomes a gripping detective novel and a cutting edge one at that.

I backed the audiobook version on Kickstarter.  Cory resorted to using this method of funding because Audible won't carry books without DRM and he insists on allowing readers to own the books they purchase.  As an added bonus, Cory got Wil Wheaton to narrate the book.  I always enjoy Wil's narration and I think he does an especially good job on books with a technology or a SciFi focus.

I strongly suggest you check this book out.  It's very compelling and made me wish I needed to commute to the office more often so I could have finished it quicker.

Saturday, April 15, 2023

An easier way to edit remote files

 


My main development machine at work is an Ubuntu desktop machine which I've got set up with cross compilers and a number of other development tools.  It's reasonably fast but because it runs Linux, it can only be connected to our lab network at work.  This used to mean having to ssh into the machine to edit files which on a fast network with X11 forwarding means I can use a GUI editor.  However I've been noticing a maddening amount of network lag between our lab network and the corporate network which means I end up waiting several seconds for things like cursor movement to take place.  That can break my train of thought.

Fortunately I discovered that WinScp has the ability to not only transfer files between systems but it can also allow me to edit files on those systems.  I launch WinScp, tell it to connect to my development machines, navigate the the appropriate directory, right click on the file I want to edit, and select launch external editor.  It can be configured to use your choice of editors on the Windows machine where WinScp is running.

Once you make the request, WinScp transfers the file to your local machine and launches your editor of choice.  Once you're done editing, it transfers the updated file back to the remote system.  The actual editing all takes place on your local Windows machine so it prevents network lag from causing a painfully slow editing session.

Sunday, March 26, 2023

Showing differences between binary files

At work I'm having to port some firmware changes to a new board.  This requires I understand the boot process in excruciating detail.  The old board boots with 3 different files stored in flash memory (bootloader, bootloader environment, and Linux file system).  I have the files as well as several raw dumps of various areas in the flash memory chip made with the "dd" command and needed to know whether there was any magic done to identify the different partitions of the flash device.

So I needed to show differences between binary files.  I normally use meld for file comparisons but it doesn't handle binary files.  It's easy to write a simple program in C to show simple byte differences but I wanted something able to display context for any differences.

It turns out that this is very easy to do in bash thanks to the ability to easily combine tools.  This is made possible by the Unix Philosophy.  The following command does exactly what I was looking for.

meld <(xxd file1.bin) <(xxd file2.bin)

So I whipped up a small shell script to make this easier and I've got a new tool for future use.  As you can see from the image, the display would be helpful in figuring out the differences between files.



Thursday, March 23, 2023

Saying goodbye to a special dog

 


We lost our very special dog to an osteosarcoma a few days ago.  He started limping a little over 4 months ago and it took a while to diagnose what was causing the problem which kept getting progressively worse.  We were so focused on figuring out what was wrong that it dominated our recent conversations about him.  I wanted to make sure it didn't overpower people's memory of the most affectionate dog I've ever met.

Bandit entered our lives a little unexpectedly about 10 years ago.  He was the third dog we've had during the 30+ years we've been married.  For some strange reason, each of them was roughly double the weight of their predecessor, progressing from 16 to 42 to Bandit's whopping 84 pounds.

Bandit had a rough start in life.  We adopted him from Rappahannock Animal Welfare League (RAWL), the same shelter where we had adopted our previous dog, Sandy, who was very sweet but much less outgoing than Bandit.  They do a wonderful job of socializing their dogs.  Apparently Bandit had been chained outside for much of his early life.  The shelter got him due to an altercation he'd had with a feral cat coupled with the fact that his first family had not seen fit to get him vaccinated against rabies.  He needed to be quarantined for 6 months for the possible rabies exposure.  They're a "no-kill" shelter but apparently that doesn't automatically apply in quarantine cases.  After seeing what a sweet dog Bandit was, they opted to keep him for the 8 months it took to get him through the quarantine period plus his recovery from being neutered because they were sure he'd be adopted.  How he stayed so friendly and loving given that rocky beginning amazes me.


My wife fell in love with the personality he displayed in the shelter's pictures of him playing with 5 beagle puppies.  His face managed to exude good-natured playfulness and joy in a way that we both found irresistible.  She also chose a smaller dog to look at in case the fact that Bandit was part pit bull (he was a lab-shepherd-husky-pit mix) made me nervous.  Any chance of me being worried about him being aggressive disappeared when they let him out of his kennel for us to meet him.  He was so affectionate that both of us ended up sitting on the floor petting him for quite a while until we were finally able to sign the adoption papers.

Since he had been chained up for much of his life, he didn't have much experience with cars.  I had to lift him into the truck where he sat nervously and stiff-legged in my wife's lap for the entire 90 minute drive home.  The only difficulty he gave us was with his initial nervousness about car rides.  He discovered that collapsing as low as possible could delay his ride for a while because it's so hard to lift an 84 pound dog who has cemented himself to the ground.  His nervousness about cars persisted for about a month until we took him to a place where we could bathe him.  He was so relieved to be done with the bath that he leapt into the back of the truck to go home.  After that, going for rides was one of his favorite activities.

 


When we adopted Bandit we lived in a suburb of DC which had lots of walking paths and he was happy to hike as far as we wanted.  Bandit usually preferred people to other dogs.  One notable exception was a dog half his size which lived near the walking path we took on a daily basis.  They loved to wrestle and often looked like tiny dinosaurs as they chest-butted each other while smiling the entire time.  It was like our own version of a Godzilla movie where the monsters are furry and friendly.  They would get so tired having fun that they would eventually collapse on the ground.  Once they had recovered somewhat, they would drag themselves towards each other to start again.

A year after we brought him home, we moved to the more rural suburbs.  Out in the country we discovered Bandit was really more of a medium-sized dog.  While technicians who came to the old house to fix things were nervous around Bandit, those visiting the new house often had dogs larger than Bandit and were happy to pet him.  Bandit always loved finding a new person to give him attention.

It was shortly after we moved to the country that he met his favorite neighbors.  Their oldest daughter bonded with him almost instantly.  She seemed to have a sixth sense about when we'd be passing their house and frequently treated him with bacon and other snacks.  After a few times being spoiled this way, his tail would start wagging wildly whenever we approached their house.

He looked forward to spend time with us each evening.  He often positioned himself between us and nudged our arms to convince us to pet him until our arms were tired and sometimes sore.  There are few things which could relax me like spending time with that affectionate bundle of love.

If I happened to drive by my wife and Bandit walking on my way home from work, Bandit would drag my wife towards the house to see me.  Bandit was a force of nature.  If he saw deer, he could spin either of us by the leash in his struggle to give chase.  Sometimes my wife would let go of his leash once they were close enough to the house to see me.  I have happy memories of him running down the road towards me and the uber-affectionate greeting I would get when he finally reached me.  The stress of the commute and a long day at work melted away instantly under his enthusiastic greeting.

There were few things which Bandit enjoyed more than having his face pet by my wife.  He would get into the strangest positions to coax her into stroking his face.

In the last few years, he had been moving a little more hesitantly and was not quite so keen to go on long walks but his sweet nature was just as strong as ever.  Those signs of him slowing down triggered me to start paying more attention to the time we had left with him.  I knew dogs as special as him don't come along often and I wanted to enjoy every precious moment.

He was sweet to the end despite being needing to take 3 potent medications for the ever increasing pain he was in while his doctors tried to diagnose his problem.  They ultimately determined it was an osteosarcoma and that the cancer had spread to his lungs.  We held out hope until the diagnosis made it obvious that we needed to let him go.

Both of us loved every minute we had with Bandit.  It's hard realizing we'll never be greeted by this big lovable goofball again.

Saturday, March 18, 2023

Exploding windows

I've encountered "exploding windows" on both Windows and Linux lately.  I try to resize a window and by clicking the window near the title bar, the window suddenly and unexpectedly expands to fill the entire vertical area of the monitor it inhabits.  Sometimes I'm able to do the simple resize operation which I wanted but randomly the operation results in an exploding window.  Perhaps the UI designer thought this was a neat feature but it causes me to curse each time I encounter it.  I'd love to figure out how to disable this behavior but each time I try to describe it in a Google search, I'm led down a rabbit hole of unrelated results.  It seems silly spending too much time researching something which while annoying only costs me annoyance and a few seconds to correct.

Sunday, February 19, 2023

Developers need IT skills

Often software developers can benefit from having skills typically found in IT support engineers.  For example I occasionally bring small embedded systems home from work since it makes working from home more productive.  It's hard to physically reconfigure equipment I've left at the office and the reset button is tough to hit across a VPN.  

In this scenario I need to be able to access the small embedded system on our home LAN as well as my build desktop machine which stays at work.  Having a VPN client which supports split tunneling makes this possible.  It requires that there be no overlap in IP addresses between the two LANs.  It also requires that I change the static IP address on the equipment I bring home to match the subnet which my home router uses.

The diagram gives a rough idea of how the split tunneling works.

VPN split tunneling diagram

Sunday, January 15, 2023

Getting paid to solve puzzles

 

The thing I enjoy most about my job developing firmware for embedded systems is that it's a lot like being paid to solve puzzles.  Many of the projects I work on are just as challenging as the old text based adventure games such as Infocom's Zork series.

The datasheets which contain information about how the chips in embedded hardware are supposed to function can be challenging to decipher.  Vendors do their best but it's not unusual for the datasheets to either be incomplete or to contain subtle inaccuracies.  A chip I developed a device driver for recently had an accurate datasheet but the device driver gave the wrong results because of an issue with the C compiler for the ARM processor.  It turns out gcc for ARM CPUs does not support signed character types by default which this chip required.  Fortunately gcc includes a compiler flag "-fsigned-char" which allows this strange behavior to be overridden.

Friday, December 30, 2022

My worst technical interview

About 38 years ago I interviewed for a software job at GEISCO (GE Information Systems).  This would be my second software position after making the switch from field engineering.  It was a systems software position, writing software to run on one of their network nodes.  At the time GEISCO supposedly ran the largest private data network in the world

One of the engineers I interviewed with felt obligated to test my software skills by asking me to write a short program on his whiteboard.   The problem was most systems software was written in assembly language at the time.  I knew 4 assembly languages which didn't overlap at all with the assembly languages he knew.  Upon learning that we didn't share a language, I asked if he still wanted me to write a program since there was no way he could determine the correctness of my program.  Being a good corporate drone, he insisted that I still needed to complete this step so he could mark it off on the interview form.  So I proceeded to write some code in GMAP, the assembly language used by Honeywell mainframes since that was the one I was most familiar with.  I guess I talked my way through it successfully because I ended up getting the job.  

My program wasn't very functional as I wrote system software and it was rare for me to need to use system calls.  I definitely had never written a system call which performed any I/O.  I believe I loaded an immediate value into a register, performed a left shift, saved it into a memory location, and then ended the program with a MME GEFINI system call which terminates the current program.

Even though I first encountered GMAP assembly language 45 years ago, I still remember the numeric value for the opcodes of a number of the instructions.  Perhaps some day I'll once again need to know that a 235 opcode is a LDA instruction (load accumulator) but I'm skeptical.  There's a lot of old knowledge I'd love to be able to purge to reclaim the memory space.

Changing the oil

I changed the oil in my commuter car today, having grown tired of the "change oil soon" messages which started appearing on the dashboard about two weeks ago.  Changing the oil is something I learned to do from helping my uncle and grandfather work on cars when I was young.  It's much quicker and somewhat cheaper to do it myself than it is to take the car to the shop since you need to include the time spent driving to the shop and waiting for the oil to be changed.

The container on the left in the picture below which now holds used motor oil always makes me think of my grandfather.  It's one of a pair of 5 gallon oil cans I have which he used for delivering heating oil during WWII.  Several times when I've taken these containers to the county recycling center to recycle the used motor oil, people have asked whether I'd consider selling them.  These cans and the other tools I inherited from him hold far too much sentimental value for me to ever consider parting with them although the idea of some yuppie paying top dollar for something like that would have made Grandad laugh.

 

I'm always pleasantly surprised to see how easy it is to access everything on this car (a Chevy Equinox).  It seems every other vehicle we've owned for the past 20 years has placed either the oil drain plug or the oil filter in an awkward spot.  Some have gone as far as hiding them above frame cross-members which makes a huge mess when the old oil drains out.  I've tried all manner of do it yourself funnels to try to coax the oil into emptying into the drain pan with varying degrees of success.


Sunday, February 14, 2021

Remote Desktop replacement

At work I have 5 Linux machines (1 desktop and 4 tiny embedded machines) and a Windows laptop in my office which I need to use.  There are KVM switches which would allow to connect my monitor, keyboard, and mouse to the machines in that large a setup but they're expensive and the cabling would be a nightmare plus I'd be stuck using just one machine at a time.  I tried using Remote Desktop and VNC to access the desktop of another machine remotely but that's cumbersome and it's slow across a VPN.  To be fair, there are situations when Microsoft's Remote Desktop works wonderfully across a VPN.  At my last job I used to use the Mac version of Remote Desktop to access my Windows laptop at work.  Since a Windows machine was the destination, Remote Desktop did a great job of data compression plus it allowed the client machine to arrange windows differently than they were arranged on my Windows laptop at the office.  So my old 27" iMac which has nearly 4k resolution gave me a better viewing setup than I had at work.

Now I use X11 (aka X-Windows) for accessing all the Linux machines I need access to.  Making this work requires a couple pieces of software.

First off, I need an X Server on my Windows laptop.  That is used to display the windows created by the remote Linux machine.  I use VcXsrv, a version of the classic xorg X Server but recompiled under Visual C++.  This recompilation allows it better access to Windows resources and I find it works better than any other X Server I've tried such as xming or cygwin's xwin.  VcXsrv needs to be run on your Windows machine prior to attempting a connection to another machine.

The next thing required is an SSH client which is capable of X11 forwarding.  That allows any programs launched using the SSH client to send their displays back to the client machine.  I use PuTTY, which has been around a long time and which can handle serial and SSH connections.

Once you've run VcXsrv on your Windows machine and then used PuTTY to connect to a Linux machine (taking care to first set the configuration to allow X11 forwarding), launching a remote program and having it display on your client machine is as simple as typing the program's name.  As an example you can try xterm which will create an X11 terminal window.  Just be sure to launch it in the background by appending an ampersand so the program is placed in the background.  Otherwise, your input and output will remain tied up by the program being launched.  The command to launch xterm this way would be "xterm &".

Saturday, February 06, 2021

Favorite books

Since I love to read, people sometimes ask me about my favorite books.  I inevitably leave some out so I thought I'd collect them in an easy-to-find place.  So here are my favorites.

Favorite authors still actively publishing
Connelly, Michael - Harry Bosch series
Crais, Robert - Elvis Cole/Joe Pike series
Doctorow, Cory - Little Brother, Walkaway, Makers, and others
Gaiman, Neil - American Gods and anything else
Hiaasen, Carl - anything
Ide, Joe - IQ series
Kowal, Mary Robinette - anything
Scalzi, John - anything
Sloan, Robin - Mr. Penumbra's 24-Hour Bookstore and others
Stross, Charles - the Laundry File series
Taylor, Dennis E - Bobiverse series
Wells, Martha - Murderbot series


Other favorite books (sorted by author name):
Adams, Douglas - First two Hitchhiker's Guide books and Dirk Gently series
Asimov, Isaac - Robot series, Foundation trilogy
Dudley, John Ball - In the Heat of the Night
Ellison, Harlan - Dangerous Visions and others
Feynman, Richard - Surely You're Joking, Mr. Feynman!: Adventures of a Curious Character
Follett, Ken - Eye of the Needle
Goldman, William - The Princess Bride & The Marathon Man
Heinlein, Robert A. - The Moon is a Harsh Mistress and his juvenile series
Irving, John - A Prayer for Owen Meany
Kidder, Tracy - The Soul of a New Machine
Kipling, Rudyard - Kim, Captains Courageous, and others
Leonard, Elmore - Maximum Bob
London, Jack - anything
Miller, Walter M - A Cantical for Leibowitz
Niven, Larry - Ringworld
Noah, Trevor - Born a Crime: Stories From a South African Childhood
Parker, Robert B. - early Spenser novels, Jesse Stone series, Virgil Cole/Everett Hitch series
Pullman, Philip - His Dark Materials trilogy
Robinson, Spider - Callahan's Crosstime Saloon series
Sayers, Dorothy - Lord Peter Wimsey series
Shute, Nevil - Trustee from the Toolroom
Sturgeon, Theodore - More Than Human and all others
Tolkien, J.R.R. - The Lord of the Rings trilogy
Twain, Mark - anything
Vonnegut, Kurt - Slaughterhouse Five and all others
Weir, Andy - The Martian
Winters, Ben H - The Last Policeman trilogy
Wodehouse, P.G. - Meet Mr. Mulliner and others

Favorite graphic novels (sorted by author name):
Ennis, Garth - Preacher, The Boys
Moore, Alan - Watchmen, V for Vendetta
O'Malley, Bryan Lee - Scott Pilgrim's Precious Little Life
Vaughn, Brian K. - Ex Machina

GNU Screen can make SSH sessions persistent

 I do a fair number of Linux kernel builds at work.  Doing a Yocto build for our target machine takes about an hour and 40 minutes for a the build to complete and the root filesystem to be prepared.  If I do that from home, there's a chance that I'll get a hiccup on my VPN connection which might disrupt the build in progress.  Even at work, I ssh into my Linux build machine from a Windows laptop and use xterm sessions for most of my development tasks.  If I kick off a build before heading home, there's always a chance that Windows will decide to do an update which could also disrupt my build.

Fortunately GNU Screen can make your sessions persistent through disruptions due to network disconnections or other reasons.  Now I make sure to start a GNU Screen session before doing my build.  I start named screen sessions with a command such as "screen -S build".  That way, if my session is disconnected, I can rejoin it with the command "screen -r build".

The one thing I don't like about GNU Screen is its default escape key, Control-A, since that interferes with the default Emacs command line editing mode in Bash.  So I've created a ~/.screenrc configuration file with the following command to change the escape key to Control-T.

escape ^tt

Sunday, January 19, 2020

Running Ubuntu Linux in a VirtualBox VM

I've recently started a new job which requires me to build software under Ubuntu Linux.  Since I don't particularly care for the Ubuntu distribution and having only a single development PC which runs Windows 10, the natural solution is to create a VirtualBox virtual machine and install Ubuntu in that.  However the combination of VirtualBox and Ubuntu caused a few problems for me.

The first problem I encountered is that VirtualBox seems determined that new VMs will all run at very low resolutions.  I've seen 640x480 being used on when running VirtualBox on both Macs and PCs running Windows 10 and it's ridiculous to be stuck with a resolution that first appeared in 1987.  At that resolution, it's difficult to get through the Ubuntu installation setup as some of the buttons appear off the screen.  That issue I believe is Ubuntu's fault.  They should make it possible to see all buttons regardless of screen resolution.  Poking around on Google, I discovered that there's a command line utility included with VirtualBox which allows you to run higher resolutions in the guest OS in VMs.  First make sure that VirtualBox is not running.  Start a command prompt with administrative privileges and navigate to the directory where VirtualBox is installed since the utility we need is not located in the command path.  The directory you want will most likely be something like "C:\Program Files\Oracle\VirtualBox".  Issue the command "VBoxManage setextradata global GUI/MaxGuestResolution any".  This plus installed the Guest Additions tools in the guest OS should allow you to change your VM to a higher resolution.

The second problem I encountered was after I installed the GUI version of my favorite editor, Vim, using the command "sudo apt install vim-gnome".  I was able to launch gvim but the menu was hidden which makes accessing a few features more difficult than necessary.  It turns out Gnome on Ubuntu has a bug which prevents some applications from displaying a menu bar.  The workaround is to define a command alias to launch Vim which undefines the UBUNTU_MENUPROXY variable.

Wednesday, November 06, 2019

Vi/Vim macros

Of all the editors I've used (and there have been a lot) I like Vi/Vim the most.  Once you get past the very steep learning curve, you can become extremely productive, in part because you almost never need the mouse.  I've been using Vi on and off since 1990 which has imprinted the commands into my fingers so I no longer think about them.  A few of the macros below have existed in some form since that time.

The macro commands below are from the _vimrc file I use to customize Vim under Cygwin running on Windows 10.  Note that characters in red below indicate control characters.  ^M is control-M which is the code produced by the Enter key on Windows keyboards.  ^[ is the code produced by the Escape key.

One of the things which saves time for me is having the ability to easily copy and paste lines from one file being edited to another.  These macros help me accomplish that.

" set temporary yank and paste filename
let @p="c:\\Users\\ViUser\\Documents\\vim\\vim.tmp"

" mark beginning of a line block (uses the a mark)
map \m ma

" yank lines to temp file (from mark to cursor pos. - uses b mark, b buffer)
map \Y :'a,.w! p^Mmb"ay'a`b

" paste lines previously yanked or deleted to temp file at cursor pos.
map \P k:r p^M

Another thing I do frequently is edit log files and search for my initials which I include in any log messages I add.  The macro below searches the log file being edited for the letters "TBD" and removes all other text.  Just remember to quit without saving or use the Vim undo command.

map \gt ^[ggVG!grep TBD^M

Monday, November 04, 2019

Customizing the bash prompt

I prefer to use a bash prompt which displays both the date and time.  That makes it easier to see when commands were issued when scrolling back through the terminal's buffer.  Here's what my prompt looks like.



The bash settings for this prompt are shown below.  You can add these lines to your .bashrc file.  For operating systems which support an admin or root user, I change the prompt's background from blue to red to give quick confirmation of that elevated privilege level.

# Attribute codes:
# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
# Text color codes:
# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
# Background color codes:
# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
PBG=44
PFG=37
TFG=36

PS1='\n\[\e]1;Term ${$} \a\e]2;\u@\h - ${PWD}\a\e[1;${PFG};${PBG}m\][\D{%m-%d} \t] eh? \[\e[m\] '

Sunday, August 12, 2018

Searching for source files which contain multiple keywords

Recently I was presented with the challenge of searching for the code which built a SQL query.  I knew what the query looked like from a log file but searching for individual terms used in the query such as SELECT, FROM, or WHERE produced hundreds of matches which I didn't want to waste time checking one at a time.

So I created the following bash script to search files for each term in order.  I used ack instead of grep for the first search so it would pick only source files of interest for me.  The results from my bash script returned only a single file which contained all the terms and it was this one which I needed to modify.

if [ -z "$2" ]                       # Is parameter #1 zero length?
then
    echo "usage -- rgt term1 term2 [term3]..."
    exit 1
fi

files=`ack -l "$1"`


# shift past the first search term argument since 
# we've already used that one 
shift  

for var in "$@"
do
    files=`echo $files | xargs grep -l $var`
done

if [ -z "$files" ]; then    # are results zero length?
    echo "no matching files found"
else
    echo "matching files:"
    echo "-------------------------------------"
    echo "$files"
fi

Quick and easy code searches

Getting presented with a large and unfamiliar code base can sometimes prove daunting.  One of the biggest challenges is how to efficiently search for things when you need to make changes.

Since I'm a big fan of platform independent tools, I had been using recursive grep searches but those frequently return too many results.  It can be difficult to limit the files searched to just the source files of interest.  Perhaps you have a unit test directory you don't wish to search.  You might also want to skip directories containing library files or other binaries.  I prefer a tool called ack to help limit the unwanted files being searched.  That prevents lots of false positives which you need to wade through.

Creating a file called .ackrc in your home directory is an easy way of setting the default settings for ack.  The following sample .ackrc file configures ack to ignore a few directories which normally don't contain code of interest.  It also sets an alternate file extension for makefiles and configures the default source languages of interest.

--ignore-dir=.svn
--ignore-dir=dist
--ignore-dir=docs
--ignore-dir=examples
--ignore-dir=lib
--ignore-dir=tests
--type-add=make:ext:make
--asm
--cc
--make

Using ack and an appropriately configured .ackrc file can significantly reduce the number of lines of matches you must check when searching your source tree for a keyword.

Tuesday, July 17, 2018

Making code searches easier


When modifying source code I'm not familiar with, it's usually necessary to do some recursive searches to figure out what to change.  You can use a simple recursive grep but I prefer a tool called ack.  You can download ack in one of several forms.  I prefer the all-in-one perl script version.  I prefer ack because it can be configured via .rc (run command) file or command line to limit the searches to files of interest.  You can ignore files with certain extensions or entire directories.  Few things are more disheartening than searching for a term within the code only to find out it appears on many hundreds of lines.  Who feels like wading through hundreds of lines to find what you're actually looking for?
 
I also use the following bash function to pipe ack's output to gvim so I can weed out unwanted matches quickly.  This is handy if the search term is a common word which is also used as a variable or function name.  I delete lines containing any variations which aren't of interest which helps reduce the job to something more manageable.

The ack script may be replaced with a simple recursive grep if you'd like.  You can also use a different editor if you don't care for Vim/Gvim.  You'll just need an editor capable of accepting input from stdin.  The following function also tells gvim to highlight the search term which I find to be a time saver.

function    ackvr    # invoke ack perl script and edits the match
{
    if [ -z "$1" ]; then
        echo "Usage -- ackvr SearchPattern
    else
        echo "ack searching for $1"
        ack "$1" | gvim -c "/$1" -

    fi
}

Saturday, November 04, 2017

Using RSS feeds to save time

I've long been a fan of RSS feeds as a way to save time when monitoring blogs.  It affords me the ability to see the headlines of new posts (and only the new posts) as they appear.  I can choose to visit the blog if the headline sounds interesting or if none of the articles catches my eye, I can mark all headlines read which makes the web site disappear in my RSS reader until the next time they add content.  It is so much faster than actually visiting a bunch of web sites that it's not funny.

I have three separate lists of RSS feeds I monitor.  I use a cross-platform app called QuiteRSS on both my Mac at home and on my Windows laptop at work.  On my phone and tablet device, I use a mobile app called Feedly to monitor a third set of RSS feeds.

At home I follow RSS feeds for beer news, book releases, and information about RetroComputing.  I don't read about these topics at work because I don't feel right about asking a company to pay me to do that.

At work I follow a number of technical RSS feeds on computer security, software development, embedded system, computer communications, and a few other tech topics.  These are all directly or indirectly related to my job.  Having these RSS feeds to read allows me to take small breaks at work while my software is building or when I'm waiting for code to download to one of my development boxes.  I'm a firm believe in the studies that say these micro-breaks improve productivity.

Whenever I have a bit of downtime during the day such as while waiting at an appointment or in line at a store, I can look at the local news sites I monitor in the Feedly app on my phone.  Feedly synchronizes feeds so when I look at those same feeds at home on my tablet device, I only see articles I haven't marked read on either device.

Thursday, October 19, 2017

Preventing strange colors for the "ls" command

I occasionally need to connect to a Linux server via ssh.  Since I use an ssh client which has a dark background, the default colors used by the ls command frequently makes directory listings difficult to read.  Fortunately you can solve this one of two ways.


For a solution which will persist throughout the ssh session, you can issue the "unalias ls" command.  That removes the alias which causes the odd coloration.  It will reappear the next time you log into that server.


For a non-persistent solution you can preface the ls command with a backslash.  Using "\ls" prevents any command alias from being used.

Thursday, October 12, 2017

Using Vim's folding feature to hide inactive conditional code

I was recently looking at some C code which had lots of conditionally compiled sections (#if, #else, #endif).  I don't care for code like that but sometimes it's a necessity when source code must support multiple hardware platforms.  In any case, it makes the code harder to read.  So I've whipped up a little macro which if placed on the #if or #else line, will use Vim's folding feature to hide that portion of code.


map    \fc   mx^%:'x,. fold


To unhide the folded section, you can issue the zd command.  I've buried that in a macro invoked by "\fd" since the more mnemonic macros are easier for me to remember.

Sunday, May 03, 2015

Gaining productivity with smartphones

I'm often surprised at how many people load their smartphones up with time wasters like games.  There were a few problem solving desktop games which appealed to me years ago but first person shooters and the mindlessly repetitive games I've seen on phones don't hold any interest for me.  Instead I've got my iPhone loaded with apps which increase my productivity and I thought others might find an idea or two in this list which might help them as well.

Cloud Storage (DropBox) - My storage needs are modest so the free account suffices for me.  This is the easiest method for sharing files between multiple desktop/laptop computers and tablets/phones.  I don't keep any sensitive data on here long term.  For times when I need to temporarily transfer such data, I create a TrueCrypt volume to store such data and transfer that up to DropBox.

Database (Bento) - Sadly, this handy little flat-file database program has been discontinued.  I use it to store all sorts of information such as books I want to read and/or purchase, books that I own (to prevent duplicate purchases in paper form), house maintenance tasks, car maintenance done, etc.  Since Microsoft has made Excel freely available, people who want similar capabilities might choose to use it instead.  It has most of the capabilities of a simple database like sorting by different fields.  If you combine it with Dropbox, you can even access your data from either your phone or a desktop PC.

Text Editor (DropText) - This gives me the ability to create and edit text files which can be shared with a desktop or laptop PC when combined with DropBox.  It allows me to maintain a paperless existence at work.  Staying paperless allows easier searching of notes.  Making notes isn't useful if you can't easily find specific data within them.

Password Manager (1Password) - Between work and home, I have around 600 unique username/password combinations to keep track of.  1Password allows me to do this gracefully while storing them securely.  I choose the WiFi Sync option so my password data isn't accessible on the cloud because I don't trust any company's cloud security.

Web Content read later app (Instapaper) - Occasionally I'll find something in a browser or one of my smartphone apps which I'd like to read later when I'll have less distractions.  Instapaper lets me store these URLs to read later.  It's available as a bookmarklet which works in all browsers.  It also works in some of my smartphone apps.

Library e-book/e-audiobook borrowing (Overdrive) - I use it mostly for borrowing e-audiobooks from our county's library system.  It keeps my 40-70 minute commute (each way) from getting boring.  Buying this many audibooks would get quite expensive in a hurry.

Podcast app (Overcast) - This makes keeping up with podcasts painless.  I've not found another podcast app which works nearly so well.

e-book reader (Kindle app) - Often I find myself unexpectedly stuck waiting somewhere like a dealer service department or a doctor's office where my choices of entertainment are old People magazines or whatever inane channel they have the TV tuned to.  Instead I opt to read whatever Kindle book is currently occupying me at home.  Since the Kindle app automatically syncs between devices, I don't even have to remember which page number was the last one I read.

PDF/ePub document reader (iBooks) - For the last 5 years or so, I've been buying all my technical books from O'Reilly in ePub format.  That allows me to have them with me on my phone in case I need to look something up quickly.  Searching is always better than trying to use the index in a paper book.  Plus I have access to my tech books both at work and at home without having to lug them home in my backpack each night.

RSS reader (Feedly app) - I keep up with tech blogs via RSS.  It lets me know when new articles are published and a glance at the title lets me know whether I'm interested enough to spend the time reading them.

Dynamic e-magazine (Zite or Flipboard) - Reading a fixed set of blogs sometimes lets interesting items sneak past me.  Zite allows me to tailor the type of information I'm interested in reading.  There's just enough serendipity in their matching that I'm usually amused or entertained by a few articles it finds for me.

So that's my list of the smartphone apps I use most often.  Are there any I've missed which you like?

Sunday, April 12, 2015

USB hubs

Many years ago while working for U.S. Robotics, I developed USB device drivers for a living and learned a fair amount about USB.  The big takeaway from that experience is I'm disappointed that Firewire didn't win the external bus contest.  It's a much better designed bus.

One of the necessities for using USB is a hub since few computers include enough USB ports for anything other than the least demanding user.  Since this is the case, it pays to understand a bit about USB hubs since you'll probably need one.

First off, there are multiple flavors of USB - 1.x, 2x, and the recent 3.X.  The key difference as far as users are concerned is the speed.  So the first concern would be to purchase a USB hub which supports the port on your computer.  Unless you've got a fairly recent computer, chances are you've got the USB 2.x flavor.  There is some degree of backwards compatibility so you could theoretically get a USB 1.1 hub but USB 1.x was so slow it's not useful for connecting anything except a mouse or keyboard.

The tricky part comes in choosing which type of power you want your hub to have.  Like most things in USB, there are multiple choices.  You can get a bus powered hub which will derive all its power from the port it's connected to or you can choose a self powered hub which needs an external power supply (AKA wall wart) to power it.  If you don't read any further, take this bit of advice - Never choose a bus powered hub!  To explain why, we'll need a little background about how USB distributes power.

The USB 2.x standard states that USB hubs (and even the ports on the back of your computer are connected to a hub) have to supply 5 volts and up to 500 milliamps (Ma) to each port.  Most likely the ports on the back of your computer offer the full 500 Ma (although a few forward thinking manufacturers offer higher current for those devices which require it).  Worst case if you plug your newly purchased USB bus powered hub with 4 ports into a port on your computer, that new hub will only have 500 Ma to power itself as well as to distribute to its 4 "downstream" ports.  A rule of thumb is that the hub itself takes 100 Ma leaving only 100 Ma for each of its 4 ports.  If you're not familiar with current ratings of devices, 100 Ma isn't a lot.  There are some USB thumbdrives which require more than 100 Ma to function.  So a bus powered hub isn't much good for devices other than a mouse or keyboard or perhaps a low powered USB thumbdrive.

That makes a pretty strong case for choosing a self powered USB hub.  This can also be trickier than it sounds.  Those wall warts aren't always adequate on cheaper USB hubs.  I've seen 8 port USB hubs with a 1000 Ma power supply.  That doesn't leave the user much better off than using a bus powered hub.  So the rule of thumb here is look for a self powered USB hub with a minimum of 500 Ma per port which means an 8 port hub would require 4000 Ma or a 4 amp power supply.

You don't need to buy the most expensive USB hub but it can save time, money, and headaches in the long run if you choose something better than the least expensive.

Sunday, March 29, 2015

Command line editing

A great many tools (including the Unix/Linux login) use a standard "readline" library which by default uses many key bindings from the Emacs editor.  It's also possible to configure readline to use Vi editor bindings.  While I'm not an Emacs user, I find it much easier to use the default bindings and to memorize a small subset of those shortcuts.  That way you don't have to worry about whether the program taking your input recognizes that you prefer Vi commands.  The login process won't know that since you are stuck using system default settings prior to logging in.

The following list shows the readline shortcuts I find most useful.  There are more of these available but many deal with situations I don't find useful very often so they're not worth memorizing for me.  If you're interested, you can easily find the rest by typing "Unix readline shortcuts" into Google.  In the following list, the "Ctrl-a" means to hold the control key down while also typing the "a" key.
  • Ctrl-a – go to the start of the command line
  • Ctrl-e – go to the end of the command line
  • Ctrl-k – delete from cursor to the end of the command line
  • Ctrl-u – delete from cursor to the start of the command line
  • Ctrl-l – clear the screen
  • Alt-b – move backward on the command line by one word
  • Alt-f – move forward on the command line by one word
I can't tell you how often I use the Ctrl-u shortcut when typing a long password during a Unix/Linux login.  There's something about not being able to see how far along you've gotten in the password entry which makes it easy to forget what's next.

Now we can combine this readline editing with the Bash command history.  You can use the up arrow to recall previously issued commands and then use these handy readline shortcuts to edit one of the commands and issue the modified command.  Sometimes that can make for a significant time savings.

Saturday, March 21, 2015

Command aliases using grep

I keep quite a few command aliases and environment variables which speeds up my use of the command line.  However sometimes it can be difficult to recall exactly what I've called one of the ones I haven't used in a while.  To help with this problem, I find it handy to define a few easy to remember command aliases to help me search my list of command aliases, environment variables, and recent command history.

alias   ag='alias | grep -i'
alias   eg='env | grep -i'
alias   hg='history | grep -i'





The need to search through command aliases and history are probably somewhat obvious.  You may ask why I find the need to keep so many environment variables though.  It turns out they're incredibly handy as shortcuts for frequently used directory paths.

For example, I always keep a shortcut called $DT for my Desktop.  That makes it very easy to move or copy a file to the Desktop using a short command like "cp filename $DT".  It removes the need for me to remember the Desktop path on all the OSes I use on a regular basis (Windows, Linux, and Mac OS X).

That may seem a simplistic use but I also keep environment shortcuts for the paths to all the SDKs (software development kits) and virtual machine shared directories I use.  That frees me up to remember more important things.

Thursday, March 05, 2015

Changing your shell prompt

I find it useful to use a colorful prompt on all the Unix or Unix-like machines I have accounts on.  It makes it much easier to scroll back to find the start of output of previously issued commands.  Otherwise you're wading through a sea of similarly colored text trying to find something which looks like your shell prompt.  That may not seem difficult but when you're dealing with makefiles which can output hundreds of lines of output, you need all the help you can get.

Look at the prompt in the following snippet from my terminal window.  It's very obvious where the prompt is and the date and time stamp in the prompt prove useful quite often.  Note that it's the date and time stamp of the prompt which follows the command output which provides an approximate time of command execution.




Another thing I like to do is to color code my prompts with the level of privileges associated with the account.  Admin accounts get a red background while user level accounts get a nice soothing blue.  You can never have too many reminders of the fact that you're using an admin account.

There are a couple ways to create a prompt like this.  The easiest is to use a handy web site like the .bashrc generator to help you configure your prompt.

I prefer having greater control over my prompt than most tools like the bashrc generator provide and I find too much information in a prompt distracting.  So the following snippet from my .bashrc file does the trick nicely.  You may need this ANSI escape sequence reference to figure out what my prompt is doing.  There are two main parts.  First I'm overriding the text in the terminal window's title bar with "Rods Terminal" followed by the working directory.  Then we jump back into the actual window, change foreground and background colors, and print our prompt.  Finally, we change back to some subdued colors for normal command output.

# Attribute codes:
# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
# Text color codes:
# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
# Background color codes:
# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
PBG=44
PFG=37
TFG=36

PS1='\n\[\e]1;Term ${$} \a\e]2;Rods Terminal ${PWD}\a\
\e[1;${PFG};${PBG}m\]\
[\D{%m-%d} \t] eh? \[\e[m\] \n'

Sunday, March 01, 2015

Making code reviews easier

Our source trees at work contain quite a few files spread out over many directories.  So reviewing code changes done by other engineers used to present a challenge.  Being handed 10 files to review used to mean manually finding each in the source tree so I could set up my diff tool with the appropriate paths to see what changes had been made to each file.  So I came up with a small bash script to automate the finding of base source files for comparison.

When I receive an e-mail containing source files to review, I copy all the modified source files to a directory called /c/review/new (this directory looks odd because I'm stuck on a Windows machine and run Cygwin to make it easier to use).  Then I cd to the top of a source tree with no changes I keep synched up with our SVN server and I type the name of my script below.  I call it "revcp" for review copy.  It finds and copies files from the current directory into a directory called /c/review/old.  Once that's done, I fire up WinMerge pointing at the old and new directories.

The only thing which can present a problem is that sometimes there are files for review for which there are multiple matches.  Makefiles are a prime example since we have quite a few of them.  The script will find all matches and prompt the user for which file to copy.

Is it perfect?  Not by any stretch of the imagination.  But for a "quick and dirty" tool which only took 15 or 20 minutes to write, it saves me quite a bit of time.  Now I no longer dread the arrival of code review requests.

#!/bin/bash
#
#   revcp (review copy)
#
# Description:
#   Given a single directory containing a group of source files to be
#   reviewed, this script will find matching files from the source tree
#   starting at the current directory for comparison.
#
# One time preparation:
#   1)  Modify NEW_DIR and OLD_DIR environment variables below to specify
#       the directory where you've placed the files to be reviewed and
#       the directory where you'd like the corresponding base files
#       to be copied.
#
# To use:
#   1)  Copy all files to be reviewed into the directory pointed to by the
#       environment variable NEW_DIR set below
#   2)  cd to a directory in your source tree above all files being reviewed
#       such as /c/svnBase/riot/client (where svnBase is the directory where
#       your svn source tree is checked out).
#   3)  Run this shell script under Cygwin or another Unix shell.
#   4)  If duplicate files are found by script the user will be prompted to
#       choose the desired file.  Once chosen, the script will manually copy
#       the selected file to OLD_DIR.
#   5)  Use WinMerge or another diff utility which can diff entire directories
#       to compare the contents of OLD_DIR with NEW_DIR
#

# This directory contains new files to review
NEW_DIR=/c/review/new

# Files found from current path will be copied to this directory
OLD_DIR=/c/review/old

FILES=$NEW_DIR/*

function FindMatchingFile
{
    CurFileName=`basename "$1"`
    NumFiles=`find . -name $CurFileName -print | wc -l`
    if [ $NumFiles -eq 1 ]; then
        echo "Copying $CurFileName"
        find . -name $CurFileName -exec cp {} $OLD_DIR \;
    elif [ $NumFiles -eq 0 ]; then
        echo "File $CurFileName not found... must be new file"
    else
        echo ""
        echo "Found multiple matches for file: $CurFileName"
        echo ""
        MatchingFiles=`find . -name $CurFileName -print`
        i=1
        for m in $MatchingFiles
        do
            echo "$i - $m"
            let "i=i+1"
        done
        echo ""
        echo -n "Enter number of the file to copy or 0 to skip: "
        read FileNum
        if [ $FileNum -eq 0 ]; then
            echo "Skipping $CurFileName"
        elif [ $FileNum -le $NumFiles ]; then
            i=1
            for m in $MatchingFiles
            do
                if [ $i -eq $FileNum ]; then
                    echo "Copying file #$i - $m"
                    cp $m $OLD_DIR
                fi
                let "i=i+1"
            done
        else
            echo "User input too large"
        fi
        echo ""
    fi
}

echo "revcp - copy files for review"
for f in $FILES
do
    FileNameToFind=`basename "$f"`
    FindMatchingFile $FileNameToFind
done

Tuesday, February 24, 2015

Changing to a sibling directory easily

I deal with multiple source trees on a daily basis.  Occasionally it's handy to switch from a subdirectory in one to the same subdirectory in a different source tree.  So I put together the following set of shell functions (similar to command aliases but they allow greater flexibility in checking parameters) to make this easier.

For example, let's suppose my current directory is ~/src/tree1/subdir1/subdir2/subdir3/ and I want to switch to the same path in the directory ~/src/tree2.  With these bash functions defined, I can type the command "cds tree1 tree2".  If I want to return to the previous directory, I can hit the up arrow key to recall the command, cursor over, and change the "cds" command to "cdsb".

# cd sideways (replaces one portion of current path with new string and changes to that directory)
function    cds
{
    if [ -z "$2" ]                           # Is parameter #1 zero length?
    then
        echo "Usage: cds DirPatternToReplace DirNewPattern"
    else
        NWD=`echo $PWD | sed -e "s/$1/$2/"`
        echo "Changing directory"
        echo "from: $PWD"
        echo "to:   $NWD"
        cd $NWD
    fi
}

# cd sideways back (same as previous command but parameters are reversed to go backwards)
function    cdsb
{
    if [ -z "$2" ]                           # Is parameter #1 zero length?
    then
        echo "Usage: cdsb DirPatternToReplace DirNewPattern"
    else
        NWD=`echo $PWD | sed -e "s/$2/$1/"`
        echo "Changing directory"
        echo "from: $PWD"
        echo "to:   $NWD"
        cd $NWD
    fi
}

Saturday, February 21, 2015

Bash history

I've always had a strong preference for using command lines interfaces (AKA CLIs) over GUIs.  I can get tasks accomplished much faster using a Unix bash shell than I can on any GUI.  Plus CLIs lend themselves to greater levels of customization than GUIs do.  If I can customize a user interface, I can adapt it to the way I prefer doing things which makes the CLI even faster to use.

One of the customizations I use in Unix style shell interfaces is to modify how commands are stored in the shell command history.  I prefer the Bash shell (AKA Bourne Again Shell).  If you don't understand the humor in that, a little time on Google can clear it up for you.

The first step I took is to specify a permanent file for my shell history.  This allows multiple shells to share the same command history which frees me from the need to remember which shell I entered a command of interest into so I can recall it.  The following lines in a .bashrc file will set this for me.

# override default history size and file settings
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTFILE=~/.bash_history

I also need to prevent my history from being wiped out when a shell is closed.

# prevent closing a shell from overwriting history (append instead)
shopt -s histappend

I also find it helpful to store timestamps for each command stored in the history.  This can be useful for shared computers where you may not be the only user entering commands.

# Store timestamp information for each command
export HISTTIMEFORMAT="%m%d %T  "

I also hate seeing duplicate commands in my command history.  One of each is sufficient and any more than that just clutter up the history unnecessarily.

# don't store duplicate commands
export HISTCONTROL=ignoredups:erasedups

And last but not least, I hate to waste space in my command history for short commands.  Typing ls is faster than looking it up in the command history so why waste space that could be storing more complicated commands that are harder to remember?

# ignore certain commonly issued commands
export HISTIGNORE="env;exit;history;ls:ps:pwd"


These lines added to your .bashrc should work on Linux, Cygwin under Windows, or Mac OS X terminal sessions.

Sunday, March 17, 2013

Sharing data

These days I split my computing time between a desktop computer at work, a desktop computer at home, a tablet device, and a smartphone.  Frequently I find myself wanting to save data in the form of a bookmark, a link to a web pace, or a note on one of these devices to access later on others.  Fortunately, there are a number of applications which make this easy.  Here are the applications I've picked to do the job.
Dropbox - Installing this application on computers and mobile devices allows effortless sharing of all types of files between devices.  Dropbox gets used by a number of other applications like PlainTest (listed below) to make life easier.
PlainText - Allows easy viewing and/or editing of text files stored on your Dropbox account from your mobile devices.  Only available on iOS devices like iPhone and iPad but you can find similar applications for Android devices.
Xmarks - Makes keeping bookmarks synchronized between browsers on desktop and laptop computers dead simple.
Instapaper - Ideal for those URLs you stumble upon on an application on one device that you want to save for later viewing.  A number of mobile device applications such as Twitter feature integration with Instapaper to simplify the task of saving interesting web pages.

Saturday, February 09, 2013

Windows development tools

It's no secret that given my own choice, I'd abandon the use of Windows PCs altogether.  However it's a sad fact of life that many of development tools I need to use at work are commercial Windows based tools.  In order to make using a Windows PC on a daily basis more bearable, I add the following tools.  An unmodified Windows PC is almost unusable to me these days.  I've no idea how anyone can get anything done on an unmodified Windows PC.
All of the following tools are free except VMware.
  • 7zip - The best archive utility I've found for Windows.  It handles all the archive formats I need to use like ZIP, RAR, and TGZ.
  • Ack - A handy little Perl script similar but superior to Grep which searches only source files.
  • ctags - Creates tags files which many editors, including Vim, can use to make source code navigation dramatically easier.
  • cygwin - Well worth it for the Unix style shell alone but you can add Windows ports of most Unix tools using this.
  • DropBox - Makes sharing files between multiple systems possible.  I take it one step further and have added it to my phone as well so my files are now easily portable.
  • FeedReader - I'm faced with periodic downtime at work where I have to wait for software builds, downloads, and tests to complete.  This RSS reader allows me to stay up-to-date on development tools and techniques during these intervals.
  • Sumatra PDF reader - Using a less popular PDF reader lowers the chances that you'll fall prey to malware using PDF files as a delivery mechanism.
  • Irfanview - Handy for cropping screenshots and other light image file manipulation.
  • Pidgin - Our office uses IM to stay in touch.  This is a nice little IM program with support for multiple IM protocols.
  • putty - I periodically need to connect to remote systems using telnet or ssh protocols.  This program makes that easy.
  • source navigator - Useful for familiarizing yourself with large bodies of source code.
  • sysinternals - These utilities proved so handy that Microsoft purchased the company which developed them.
  • TeraTerm - A decent terminal emulator.  Handles both telnet and serial port connections but I only use it for its serial capabilities.
  • Thunderbird - I use this to monitor my home email account.
  • TortoiseSvn - Integrates the Subversion source code control system with Windows Explorer.
  • TrueCrypt - A useful program for encrypting files, directories, and disk images.  I use it for some of the files I store on DropBox.
  • VMware - I need to run Linux software occasionally.  VMware is the fastest and easiest method I've found of doing this without using a separate PC. 
  • Winmerge - This is the best visual tool I know of for displaying differences between files and for merging changes from one file to another.
  • winscp - Handy for transferring files between systems using ftp, sftp, or scp protocols.
  • Wireshark - The best Ethernet packet sniffer.  It understands lots of protocols and can be extended to understand new ones if necessary.
  • Vim - My favorite editor.  It's a Vi clone with modern features like color syntax highlighting and column editing.
  • Xvi32 - My favorite hex editor.