LJ Archive


Work the Shell Column, June 2015

In “When Is a Script Not a Script?”, Dave Taylor cautions that a loop like for f in * would have problems handling filenames with spaces—for example, “hello world”. However, field separator processing is not performed on the generated strings and f would be properly set to “hello world”.

In the two find examples, the semicolons that terminate the -exec clauses should have been quoted. Most likely a backslash was lost between the author and the printer. In the first example (-exec chmod) the “plus” terminator would have been a good alternative that would not require quoting. Because the “+” terminator aggregates filenames for fewer command executions, it would not be a good alternative for the second example (-exec echo).

Dave's use of the file command to classify files with executable permission is laudable. However, Dave's shell bias (shared by myself) comes through as his code does not account for other scripting languages, such as Awk or Perl.

The file command looks for “magic strings” to identify the file type. The strings it knows about are listed in a file appropriately named “magic”. It is located in /usr/share/misc on my system and has its own man page, man -s 5 magic. My version of file can identify about 20 different scripting languages. They all report with the words “script” and “executable”.

Compiled programs are also understood by file. Rather than looking for matching C source files, Dave could have checked the file description for the words “executable” and “ELF” (Executable and Linkable Format).

Jon LaBadie

Dave Taylor replies: You raise some good points here. Thanks for writing!

Scanning on Linux Distributions

Regarding Alan Lewis' letter in the June 2015 issue about printing and scanning, I have found that Hewlett-Packard multifunction printers combined with HP's excellent (free-to-a-good-home) HPLIP software fully supports all printer functions over many years and three or four HP printers. Currently, I have an HP OfficeJet Pro 8600: Ethernet interface, print, automatic duplex print, scan, copy and fax (built-in telephone connection). Everything works, works the way I expect, and I have zero problems. I also have an older (about 12 years) HP Business Inkjet 2280tn with two trays and Ethernet that is fully supported (it doesn't do much but print) by HPLIP.

I bought a Canon Pixma iP 6310D a few years back. Zero Linux support from Canon. It's a doorstop, and it's free to a good home if somebody wants to pay the shipping.

HPLIP is generally included with most Linux distributions (mine is Slackware). HP fixes any problems quickly (and adds new printer support), and installs and integrates with CUPS quickly and easily—just run hp-setup and away you go.

Why go anywhere else, particularly manufacturers that don't provide Linux support?

Thomas Ronayne

Although I agree HP is usually good about Linux compatibility and Canon is horrible, it's still always a good idea to check before buying.—Shawn Powers

Typo in the June 2015 Issue

The find command at the bottom of page 11 in the Letters section is wrong [see the “Pipes and Xargs” letter]:

find / -name "*.mp3' -exec rm '{}' \;

It should be this:

find / -name "*.mp3" -exec rm '{}' \;

The quotes must match.

Alan Olsen

You are, of course, correct. I suspect Richard's right pinky is a little quicker than his left, and Shift wasn't pressed in time! (As far as me not catching the error, sadly I don't have a crafty excuse for that.) Thanks, Alan.—Shawn Powers

A New Algorithm

The following may be of interest to your readers:


The following is an algorithm to factor pq into the 
individual primes p and q that were multiplied 
together to form pq. It is not required to know any 
primes in the beginning and no divisions are required.

Input the number pq to begin and take the square 
root of pq.
Insure the square root is negative by subtracting 1 
if required.
Set the variables p and q equal to the negative 
square root.
Decrement p by 2 and increment q by 2.
Set up a continuous loop.
Set variable a equal to p*q.
Set up for/next loop which will terminate when a 
becomes greater than pq.
Within the for/next loop:
Add p to a.
Increment q.
When a and pq are exactly equal terminate the 
for/next loop and goto end of program.
When the for/next loop terminates because a is 
greater than pq decrement q by 1 and
decrement p by 2 then goto the beginning of the 
continuous loop.
When a and pq are equal and the program terminates 
p will be the original p prime
used to form pq and q will be the other prime. */

#include <stdio.h>
long long i,pq,x,y,sr,a,m,p;
int main(void)
/* pq = 299; */
/* pq = 989; */
/* pq = 7957; */
/* pq = 16972174847; */
/* pq = 52364476296131; */
pq = 2549809323176597;
/* pq = 29837383766136799; */
/* pq = 303703809540747433; */
/* pq = 1043931805398125881; */
/* pq = 2786765675348933501; */
/* pq = 18446744073709551617ll; */

printf("pq = %llu\n",pq);

/* Routine to calculate sr, the square root */
m = sr = p = 1;
while(m <= pq) { p += 2; m += p; sr++; }
if((sr % 2) == 0) sr--;  /* If the square root is even,
                          * make sure it is odd */
x = y = sr;

printf("sr = %llu\n", sr);

/* Adjust x and y to skip the first loop iteration since
 * a square area cannot equal a rectangular area */
x -= 2;
y += 2;

a = x*y;  /* Set a equal to the area to expand 
           * toward the area of pq */

/* The for loop expands area a toward area pq by 
 * multiple values of x until either they are equal
 * or area a is larger than pq */
for(i = 0; a < pq; i++) {
    a += x;
    if(a == pq) goto End;

/* If a and pq are not equal, decrement x by two for 
 * the next try and remove the excess y count 
 * caused by the for loop */
x -= 2;

goto Loop;


printf("The rectangle pq has prime sides %llu and %llu.\n",x,y);
return 0;

Glen A. Dobbs

Glen, I hope I wasn't just “Rick Rolled”, because your math and scripting are beyond my ken. I'm sure others will appreciate the script though. Thank you!—Shawn Powers

A General Issue with GUIs

Some GUIs, before initiating an action, present the user with check boxes for “OK” and “Cancel”, in that order. Others in the same situation present the user with boxes for “Cancel” and “OK”, in that order. Once in a while, out of habit, I punch the unintended box. This could be a Very Bad Thing if I meant to punch “Cancel” and instead punched “OK”. This is one case where we need an autocrat to dictate that only a specific style may be used.

Jim Haynes

I totally feel your pain, Jim! I have no solution, nor do I have the global influence to fix such things, but there should be an IEEE standard for dialog boxes!—Shawn Powers

Scanning Tips for Linux

I may have part of a solution for Alan McConnell's difficulties with his Canon scanner (see the Letters section in the June 2015 issue). Based on the description of the problem that he sent to Canon, I suspect he has permissions issues (a problem I have become quite familiar with using my HP printer/scanner). Try changing the ownership of the device files located at /dev/bus/usb/xxx/yyy where you replace xxx and yyy by the two numbers shown after libusb (in Alan's post, that would be 003 and 004). By default, these devices are owned by root; you need to have ownership of the files yourself (unless you don't mind making them world-read and writeable, which is probably a bad idea). Once you have fixed the ownership, running sane-find-scanner should return the human-readable version of the vendor and product information. Hope this helps!

Greg Mahlon


In the June 2015 issue, in my “Doing Stuff with Docker” article, I wrote this:

sudo docker run -d --net="host" \
-v /mnt/docker/plex:config \
-v /mnt/videos:data \
-p 32400:32400 \

But, it should be this:

sudo docker run -d --net="host" \
-v /mnt/docker/plex:/config \
-v /mnt/videos:/data \
-p 32400:32400 \

(There should be slashes after the colons.)

I apologize for any frustration.

Shawn Powers

Linux Drivers for Canon and Other Unsupported Scanners

VueScan, a non-FOSS, non-free ($75) scanner program, may restore functionality to Canon and other scanners lacking drivers for Linux (or Windows 7). I've used the program to restore functionality to a Nikon LS-5000 slide scanner at work (unsupported in Windows 7) and an older Epson scanner at home (no Linux driver). The program was easily worth the $150 for the two licenses. Free trials are available from the publisher: hamrick.com.

I am pleased that the Linux desktop market is large enough to attract developers. Most of the software I use is free and open source. There is also room on my Linux desktop for non-free, closed software.

Update: I just double-checked and see that the price of the professional license for VueScan has gone from $75.00 to $89.00 and includes free upgrades for life. The software supports Macs as well as Linux and Windows.

Steve Johnson

I can second Steve's support for VueScan. The devices it supports work very, very well with it.—Shawn Powers

Re: June 2015 Letters—Canon MF4770n and SANE

The sane-pixma back end is supposed to support the Canon MF4770n on USB and Ethernet. SANE's Web site says the status is “good”, which I assume means that SANE works with the MF4770n, but not all of the device's features are available.


January 2015 Issue

I admit that I am way behind on my reading, but I just finished the January 2015 issue, and I am excited to try some things.

I read Jeramiah Bowling's article “How to Perform an Internal Security Review”, and I was thinking that it would be a cool thing to try just on my home network.

Then it occurred to me that in the same issue Shawn Powers wrote “Vagrant Simplified”, and then the light bulb went on for me. I went looking, and sure enough, there is a Vagrant box for Kali Linux.

I haven't gotten any further than that, but the Vagrant box is downloading now, and soon I expect to be able to follow Jeramiah's steps in my own environment.

Thanks for a great set of articles!


Awesome! I love when our various articles complement each other. Have fun, Werner!—Shawn Powers

Erratum, II

First, congratulations for the great work! In Shawn Powers' “Gettin' Sticky with It”, in the June 2015 Upfront section, he uses the example ls -l /bin/ping to show the SUID set in the permissions string, but in Fedora 22 and CentOS, it isn't there, because it's not defined by a permission, but by a capability. In the ping, if you use the getcap command, it will return the following capabilities:


For more info about them, see man capabilities. Thanks!


Gosh darn progress! Back in my day, our binaries were SUID, and we liked it! Seriously though, thanks for the info. I didn't check all major distros, and I probably should have done so.—Shawn Powers

More on “Gettin' Sticky with It”

In response to the question that Shawn Powers had about the sticky bit [see the June 2015 Upfront section], its original use had no effect on directories (folders). Instead, it was used on executable files (compiled programs, to be specific), so that when the program was run, its text area would “stick” in the swap space. So “t” stands for “text”. This also explains the origin of the term “sticky bit”.

Mark Iszler

Cool info Mark, thanks!—Shawn Powers

Hacking a Safe with Bash

I know it's late June and I'm responding to an article from the May 2015 issue—sometimes I have more magazine than month and I get behind—but I wanted to comment on a few things that jumped out at me when reading this fine article [see Adam Kosmin's “Hacking a Safe with Bash”]. I did learn a thing or two, and the focus of the article was not shell script programming, but ...

I write a lot of shell scripts in my job and off hours, and when I write a production-level script, my goal is portability and safety.

1) Even though the article was focused on using the Bourne-Again shell, there was nothing there that really needed any of that shell's advanced features, and I would opt for the Bourne shell (/bin/sh), which every POSIX-compliant system must have. For this script, it would just be translating all $(...) constructs to back ticks `...` and a few other changes. On many systems, /bin/sh is either a link to /bin/bash, /bin/dash or /bin/ash, which all understand the Bourne shell syntax as a subset.

2) The Bourne shell (and Bash) has special ${} constructs for setting a default value if the given environment variable doesn't exist—for example, SOURCE_DIR=${SOURCE_DIR:-$HOME/safe}.

3) Instead of tar, I would use cpio, which works “natively” with find and xargs, and is designed to archive a list of files passed in via stdin. I would also use the -0 for each, which is a useful GNU-ism for delimiting the filenames with the NULL character and allows the use of filenames with spaces.

4) I notice a number of “rm”s after some action is performed. This is probably the thing that caught my attention the most. If the action failed, the script would be wiping out the safe directory or file contents, losing everything! In all such cases, I would append the rm command to the previous action with the && control operator or onto a test for the existence of a non-zero-file-length safe file or directory existence—something that would give that warm fuzzy feeling that the action succeeded.

5) All the commands used, like rm, tar and shred, are not fully qualified, so the first executable found in the PATH list will be used. This can lead to a hacker placing a rogue executable script to intercept, log or screw with your actions. So I make variables for all the commands I use—for example, RM=/bin/rm; TAR=/bin/tar; and so on. For executables that may not be in the same location of differing systems, you can quickly test the few likely paths and set the variable accordingly.

I found the article useful, and I'll probably hack my own version soon. Thanks for the fine article.

R.K. Owen

Adam Kosmin replies: All great stuff. Would you be willing to send a PR (https://github.com/windowsrefund/safe)?

LJ Archive