Contents

Editorial



February 2018

Lately there's been quite a lot of noise about the Spectre and Meltdown bug. What is it all about? There are many sources where you can read about it but this article from forum member jamesbond satisfied my curiosity, well almost anyway.

Recently I had a need to transfer some emails from Microsoft Outlook to Seamonkey Mail which was a bit of a challenge until I found the right tools. Read about it here.

6502coder has provided a couple of interesting tutorials for the more advanced users.

In the past I'm sure I have written about QEMU which is a very nice virtualiser. An alternative is VirtualBox which many would say is even better. Find out where to download, compile and install it.

Each month I try to provide a useful script or two. The weather script here is quite nice.

Symlinks are a powerful part of Linux. This month I have attempted to explain where and how to use them here.

This month's crossword by greengeek is all about Puppies, not Puppy Linux. How well do you know your dogs?

smokey01

Distro's

The Puppy Linux Discussion Forum is the main source for a lot of the information repeated here. Where appropriate, links will be provided so you can read first hand about the distribution development. This section will likely just provide highlights as a starting point.

Fatdog64-721

Fatdog64-720 and 721 Final [11 Jan 2018]


Fatdog64 721 is a special release meant to address two things:

1. Updated Linux kernel 4.14.12 with fixes for Spectre and Meltdown.
2. Updated kernel-modules.sfs containing missing firmware that was reported in 720.
Slacko 5.7.1

Slacko 5.7.1 woof-CE testing

Sailor Enceladus has released a new version of Slacko 5.7.1. using the slackware 14.0 repository.



Software

This months covers:

Google-drive Filemanager

Google-drive Filemanager

Google-drive Filemanager - Written by fredx181



Tutorials

Moving emails from Microsoft Outlook to Seamonkey Mail - smokey01
AWK - 6502coder
M4 - 6502coder
Gtkdialog Part 4 -smokey01
Email

Managing .eml files - Written by smokey01

Recently I was asked by a friend to have a look at his computer as it was slow to the point where it was almost unusable. The computer turned out to be about thirteen years old and was running Windows XP. A good clean up and a defrag would probably have improved performance but computers have moved on a little since 2005. I suggested it was probably time to upgrade so he bought a new AMD A8 Quad core with 8GB of ram. It came with a 1TB HDD, DVD RW, Multi-card readers and quite a few 3.1 USB ports. In other words a pretty nice machine all for $AUD475.00 delivered.

I installed Fatdog-720 onto his new machine which took about five minutes. It would have been quicker but I discovered the the HDD was not formatted so I formatted it to Ext3. I used the default installation tool in Fatdog after booting from a USB drive.

Before I install an operating system for anyone I normally ask a few questions about their requirements. What they tell me at the beginning of the installation and at the end often differs quite considerably, this was no exception. The three main requirements my friend had was: a browser, email client and a solitaire card game. What he didn't tell me was he wanted to keep a whole bunch of emails he had saved on his Windows machine in Outlook. First I didn't give it much thought but when it came to move the saved emails I discovered a problem. Exporting the emails from Outlook was easy enough albeit they had to be done one at a time and there were many. I exported them as .eml stand alone files. This method is quite good as it keeps attachments intact. The real problem started when trying to import them into Seamonkey Mail. There is no default function to do this. Mr Google helped me find a plug-in called ImportExportTools and what a great little plug-in this is.

What I did next was make a bunch of local folders with appropriate names. Right click on the folder I wanted to import the .eml files to, select ImportExportTools then select Import messages. A dialog will open so you can navigate to where the saved .eml files are located. Select the files you wish to import and click on Open.

That's it job done.

Below is a snapshot of the options ImportExportTools provides.



AWK as Interpreted C

AWK as Interpreted C
by 6502coder

C is a widely-known programming language, but not every C programmer is familiar with AWK. The syntax of AWK is very much like that of C (this was intentional on the part of AWK's creators). We can take advantage of this to use AWK as a sort of interpreted C, to write simple C-like programs that don't need to be compiled. To illustrate the technique, I'll use an example involving a downloading problem.

I use the DownThemAll (DTA) plug-in for Firefox/SeaMonkey to download files en masse. Usually I do this using DTA's ability to accept a primitive sort of regular-expression specification of the file names. But another nice feature of DTA is the ability to feed it a text file listing the files to be downloaded.

One trick that some web sites use to defeat mass downloading is to scatter a set of files across multiple directories. For example, instead of having

www.naturewallpapers.com/islands/crete01.jpg
www.naturewallpapers.com/islands/crete02.jpg
...
www.naturewallpapers.com/islands/crete50.jpg

they might have the files arranged as

www.naturewallpapers.com/islands/foo572/crete01.jpg
www.naturewallpapers.com/islands/foo573/crete02.jpg
...
www.naturewallpapers.com/islands/foo621/crete50.jpg

Notice that the "foo*" directory names follow a simple pattern, as is often the case. (Thank goodness for lazy webmasters!)

If we had this list in a text file, we could feed it to DTA. But how to create this list in the first place? Bash, Perl, and Python are fine options, but C is the language I'm most at home with, so that's what I want to use. A simple C program with a printf() in a loop is the obvious solution, but here's where AWK comes in. We can run this AWK command:

awk 'BEGIN { for (k=1; k<=50; k++) printf("www.naturewallpapers.com/islands/foo%3d/crete%02d\n", 571+k, k); }'

which does the job using code which -- aside from the "BEGIN" label -- is 100% good old C.

Of course this is a trivial example, just to illustrate the technique. The point is that there are many times when I can use a BEGIN block in AWK instead of writing and compiling an actual C program. No need to load the devx SFS, no compilation step. If you're fluent in C, this trick can be handy.

The M4 Macro Processor

The M4 Macro Processor
by 6502coder

M4 is another of those ancient command-line tools that Linux has inherited from UNIX. It is a handy text-processing tool that deserves to be better known.

M4 allows you to define and use macros, which are symbolic names assigned to pieces of text. C programmers will be familiar with #define macros, which are processed by the cpp preprocessor. M4 provides the same sort of capabilities as cpp, but whereas cpp is specific to C source code, M4 works with arbitrary text files.

Let's take a look at M4 in action. Here are two text files, sample1 and sample2, followed by the results of running M4 on sample1. (The "-n" option to cat adds the line numbering.)

$ cat -n sample1
1 define(`Bill', `William Hawksley Bryant Carmichael IV')
2
3 I said hi to Bill.
4 But Bill didn't answer.
5 -------------------------1
6 define(`money', `the legal tender of $1 is $2')dnl
7 For example, money(Waluwalu Island, seashells),
8 whereas money(Technopolis, Bitcoin).
9 -------------------------2
10 include(`./sample2')dnl
11 I'M THE LAST LINE

$ cat -n sample2
1 This is text found in "sample2", which will be
2 included into sample1

$ m4 sample1 | cat -n
1
2
3 I said hi to William Hawksley Bryant Carmichael IV.
4 But William Hawksley Bryant Carmichael IV didn't answer.
5 -------------------------1
6 For example, the legal tender of Waluwalu Island is seashells,
7 whereas the legal tender of Technopolis is Bitcoin.
8 -------------------------2
9 This is text found in "sample2", which will be
10 included into sample1
11 I'M THE LAST LINE

Here's what's going on:

1. On line 1 of sample1, we defined a macro named "Bill", which is defined to be a long name. In the output of M4, you can see that "Bill" has been expanded into the long name. This is a basic parameterless macro, which expands a symbolic name into a specified constant string.

IMPORTANT: the arguments to the macro are strings that begin with a BACKQUOTE character and end with a regular QUOTE (apostrophe) character.

Notice that the output from M4 starts with two blank lines. One of these comes from line 2 of sample1. The other comes from line1, i.e. from the line that contains the macro definition. This "extra" blank line may or may not be important, depending on what kinds of text you are working with. If it is undesirable, it can be suppressed, as I'll show later.

2. Line 6 of sample1 defines a macro named "money", which takes two arguments (parameters). As you can see in lines 6-7 of the output, this macro has been expanded, inserting the two parameters into the appropriate places. This is a classic example of defining a text template to save a lot of repetitive typing.

Note that "dnl" appears after the definition of the "money" macro. The "dnl" tells M4 to ignore everything up to AND INCLUDING the next newline character. This suppresses the "extra" blank line that we saw with the "Bill" macro. This is also how you can insert comments into a file, e.g. to document the purpose of a macro, as in

dnl Macro money
dnl Arguments are Placename and Currency
define(`money', `the legal tender of $1 is $2')dnl

3. Line 10 of sample1 contains an "include" directive, which tells M4 to go get the contents of the specified file and use them as if they were part of the current file. Again, C programmers will recognize this as being similar to the #include directive to the C preprocessor. The "include" directive is commonly used with M4 to insert boilerplate text, or to grab a file containing a set of useful macro definitions.

Once again, note that the pathname argument to the "include" directive is enclosed by a BACKQUOTE on the left and a QUOTE on the right.

There is a lot more to M4 than is shown in this quick introduction. If you'd like to investigate it further, "man" pages for M4 are easily found on the web. Since it is considered a standard part of the UNIX/Linux programming toolset, you should be able to find M4 included in the devx SFS of any Puppy.

Gtkdialog Part 4

Written by smokey01

This month we are going to have a look at radio buttons. Radio buttons provide a simple way to make a choice from multiple options. You can only make one choice from the available options.

Most of these example are sourced from the gtkdialog-514 examples. Most Puppy distributions have these examples included in the devx file. If you load the devx SFS for your distribution you should find them at: /usr/share/doc/gtkdialog-514/examples

Below is an example of a few Radio Buttons.



Here is the code:

#!/bin/sh

[ -z $GTKDIALOG ] && GTKDIALOG=gtkdialog

funcbtnCreate() {
echo '<button image-position="'$2'">
<label>"'"$3"'"</label>
<input file stock="'$4'"></input>
<action>echo "'"$5"' '$1'"</action>
<action function="'"$3"'">'$1'</action>
</button>'
}

funcrdoCreate() {
echo '<label>'"$2"'</label>
<variable>'$1'</variable>
<action>echo '$1' changed to $'$1'</action>
</radiobutton>'
}

MAIN_DIALOG='
<window title="RadioButton Advanced" resizable="false">
<vbox border-width="15" spacing="10">
<text>
<label>"Groups of radiobutton widgets are bound by containers
i.e. the notebook, vbox, hbox and frame widgets."</label>
</text>
<hseparator></hseparator>
<hbox homogeneous="true">
<radiobutton>
<action>if true enable:btnCancel</action>
'"`funcrdoCreate rdo0_0 "Enable the Cancel button"`"'
<radiobutton>
<action>if true disable:btnCancel</action>
'"`funcrdoCreate rdo0_1 "Disable the Cancel button"`"'
</hbox>
<hbox homogeneous="true">
'"`funcbtnCreate rdo0_0 0 Disable gtk-no Disabling`"'
'"`funcbtnCreate rdo0_0 0 Enable gtk-yes Enabling`"'
'"`funcbtnCreate rdo0_1 0 Disable gtk-no Disabling`"'
'"`funcbtnCreate rdo0_1 0 Enable gtk-yes Enabling`"'
</hbox>
<frame>
<radiobutton>
<action>if true enable:btnOK</action>
'"`funcrdoCreate rdo1_0 "Enable the OK button"`"'
<radiobutton active="true">
<action>if true disable:btnOK</action>
'"`funcrdoCreate rdo1_1 "Disable the OK button (initially active=\"true\")"`"'
</frame>
<hbox spacing="20">
<vbox>
<radiobutton draw-indicator="false">
'"`funcrdoCreate rdo2_0 "draw-indicator=\"false\""`"'
<radiobutton draw-indicator="false">
<default>true</default>
'"`funcrdoCreate rdo2_1 "default directive contains \"true\""`"'
</vbox>
<vseparator></vseparator>
<vbox>
<radiobutton>
'"`funcrdoCreate rdo3_0 "Some label"`"'
<radiobutton inconsistent="true">
'"`funcrdoCreate rdo3_1 "inconsistent=\"true\""`"'
</vbox>
</hbox>
<hseparator></hseparator>
<hbox homogeneous="true">
<button cancel><variable>btnCancel</variable></button>
<button ok><variable>btnOK</variable></button>
</hbox>
</vbox>
</window>
'
export MAIN_DIALOG

case $1 in
-d | --dump) echo "$MAIN_DIALOG" ;;
*) $GTKDIALOG --program=MAIN_DIALOG ;;
esac

Compiling

This is a good section to discuss how to compile software. Compiling is not everyone's cup of tea but the more people that can manage it, the longer life Puppy will have.

The hardest part of compiling is the build recipe as there are so many options. Let's include some proven recipes here.

You must have the devx loaded as this is where most of your compiling tools reside. In some cases you may also need to have the kernel sources loaded.

VirtualBox

Written by smokey01

Back in March last year I write a short article about QEMU. QEMU is software that allows you to run various virtual machines. In other words you can run more than one operating system at a time using your main OS as your host.
Another nice piece of software that allows you to do this is VirtualBox.

VirtualBox for many Puppies is a good place to start learning about and obtaining a copy of VirtualBox.

VirtualBox home page

Two of the best ways to ensure VirtualBox will run on your machine is to either compile it from source or download the .run file and install it. I find installing from a the .run file is easier. As I write this the latest version is 5.2.6. I have included the 32bit and 64bit links below.

VirtualBox-5.2.6-120293-Linux_x86.run

VirtualBox-5.2.6-120293-Linux_amd64.run

To be able to install the .run file you need to have the devx and kernel sources loaded as some modules do need to be compiled.

You need to make sure the .run file is executable. (With Rox right click > Permissions > Yes)

Open a terminal in the same directory as the .run file and type:

VirtualBox-5.2.6-120293-Linux_x86.run install

Now sit back and let it do its magic. Answer any questions that may pop up. You may see a few error messages regarding symlinks but it didn't stop it working here under Fatdog64-710.

If everything has progressed as it should, you should see a menu entry for Oracle VM VirtualBox under System.

WARNING
For some systems like Fatdog64-720, and possibly others, you might have problems as the readlink application is part of busybox and fails. The full readlink package does exist in Fatdog64-720 but the VirtualBox .run script calls a symlink that points to the busybox version of readlink. To temporarily fix this problem rename the symlink so the .run script will use the full version. Once installed you can rename your symlink back to its original name.
Scripts & Code

A nice terminal weather script - written by Alexander Epstein.

weather

The article written by smokey01 and the main weather script was written by Alexander Epstein

This is quite a nice weather forecaster written by Alexander Epstein. Place the script in one of your bin directories EG: /usr/local/bin

For help type weather -h

To get a three day weather forecast for Sydney Australia type: weather Sydney in a terminal.



#---------------------------------------------------------- Beginning of weather script --------------------------------------------------------------

#!/usr/bin/env bash
# Author: Alexander Epstein https://github.com/alexanderepstein

currentVersion="1.21.0" #This version variable should not have a v but should contain all other characters ex Github release tag is v1.2.4 currentVersion is 1.2.4
LANG="${LANG:-en}"
locale=$(echo $LANG | cut -c1-2)
unset configuredClient
if [[ $(echo $locale | grep -Eo "[a-z A-Z]*" | wc -c) != 3 ]]; then locale="en"; fi

## This function determines which http get tool the system has installed and returns an error if there isnt one
getConfiguredClient()
{
if command -v curl &>/dev/null; then
configuredClient="curl"
elif command -v wget &>/dev/null; then
configuredClient="wget"
elif command -v http &>/dev/null; then
configuredClient="httpie"
elif command -v fetch &>/dev/null; then
configuredClient="fetch"
else
echo "Error: This tool requires either curl, wget, httpie or fetch to be installed\." >&2
return 1
fi
}

## Allows to call the users configured client without if statements everywhere
httpGet()
{
case "$configuredClient" in
curl) curl -A curl -s "$@" ;;
wget) wget -qO- "$@" ;;
httpie) http -b GET "$@" ;;
fetch) fetch -q "$@" ;;
esac
}

getIPWeather()
{
country=$(httpGet ipinfo.io/country) > /dev/null ## grab the country
if [[ $country == "US" ]]; then ## if we're in the us i'd rather not use longitude and latitude so the output is nicer
city=$(httpGet ipinfo.io/city) > /dev/null
region=$(httpGet ipinfo.io/region) > /dev/null
if [[ $(echo $region | wc -w) == 2 ]];then
region=$(echo $region | grep -Eo "[A-Z]*" | tr -d "[:space:]")
fi
httpGet $locale.wttr.in/$city,$region$1
else ## otherwise we are going to use longitude and latitude
location=$(httpGet ipinfo.io/loc) > /dev/null
httpGet $locale.wttr.in/$location$1
fi
}

getLocationWeather()
{
args=$(echo "$@" | tr " " + )
httpGet $locale.wttr.in/${args}
}

checkInternet()
{
httpGet github.com > /dev/null 2>&1 || { echo "Error: no active internet connection" >&2; return 1; } # query github with a get request
}

update()
{
# Author: Alexander Epstein https://github.com/alexanderepstein
# Update utility version 2.2.0
# To test the tool enter in the default values that are in the examples for each variable
repositoryName="Bash-Snippets" #Name of repository to be updated ex. Sandman-Lite
githubUserName="alexanderepstein" #username that hosts the repository ex. alexanderepstein
nameOfInstallFile="install.sh" # change this if the installer file has a different name be sure to include file extension if there is one
latestVersion=$(httpGet https://api.github.com/repos/$githubUserName/$repositoryName/tags | grep -Eo '"name":.*?[^\\]",'| head -1 | grep -Eo "[0-9.]+" ) #always grabs the tag without the v option

if [[ $currentVersion == "" || $repositoryName == "" || $githubUserName == "" || $nameOfInstallFile == "" ]]; then
echo "Error: update utility has not been configured correctly." >&2
exit 1
elif [[ $latestVersion == "" ]]; then
echo "Error: no active internet connection" >&2
exit 1
else
if [[ "$latestVersion" != "$currentVersion" ]]; then
echo "Version $latestVersion available"
echo -n "Do you wish to update $repositoryName [Y/n]: "
read -r answer
if [[ "$answer" == [Yy] ]]; then
cd ~ || { echo 'Update Failed'; exit 1; }
if [[ -d ~/$repositoryName ]]; then rm -r -f $repositoryName || { echo "Permissions Error: try running the update as sudo"; exit 1; } ; fi
echo -n "Downloading latest version of: $repositoryName."
git clone -q "https://github.com/$githubUserName/$repositoryName" && touch .BSnippetsHiddenFile || { echo "Failure!"; exit 1; } &
while [ ! -f .BSnippetsHiddenFile ]; do { echo -n "."; sleep 2; };done
rm -f .BSnippetsHiddenFile
echo "Success!"
cd $repositoryName || { echo 'Update Failed'; exit 1; }
git checkout "v$latestVersion" 2> /dev/null || git checkout "$latestVersion" 2> /dev/null || echo "Couldn't git checkout to stable release, updating to latest commit."
chmod a+x install.sh #this might be necessary in your case but wasn't in mine.
./$nameOfInstallFile "update" || exit 1
cd ..
rm -r -f $repositoryName || { echo "Permissions Error: update succesful but cannot delete temp files located at ~/$repositoryName delete this directory with sudo"; exit 1; }
else
exit 1
fi
else
echo "$repositoryName is already the latest version"
fi
fi
}

usage()
{
cat <<EOF
Weather
Description: Provides a 3 day forecast on your current location or a specified location.
With no flags Weather will default to your current location.
Usage: weather or weather [flag] or weather [country] or weather [city] [state]
weather [i][M] get weather in imperial units, optional M means windspeed in m/s
weather [m][M] get weather in metric units, optional M means windspeed in m/s
weather [Moon] grabs the phase of the moon
-u Update Bash-Snippet Tools
-h Show the help
-v Get the tool version
Examples:
weather
weather Paris m
weather Tokyo
weather Moon
weather mM
EOF
}

getConfiguredClient || exit 1

while getopts "uvh" opt; do
case "$opt" in
\?) echo "Invalid option: -$OPTARG" >&2
exit 1
;;
h) usage
exit 0
;;
v) echo "Version $currentVersion"
exit 0
;;
u) checkInternet || exit 1 # check if we have a valid internet connection if this isn't true the rest of the script will not work so stop here
update || exit 1
exit 0
;;
:) echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done

if [[ $# == "0" ]]; then
checkInternet || exit 1
getIPWeather || exit 1
exit 0
elif [[ $1 == "help" || $1 == ":help" ]]; then
usage
exit 0
elif [[ $1 == "update" ]]; then
checkInternet || exit 1
update || exit 1
exit 0
fi

checkInternet || exit 1
if [[ $1 == "m" ]]; then
getIPWeather "?m" || exit 1
elif [[ "${@: -1}" == "m" ]];then
args=$( echo "${@:1:(($# - 1))}" ?m | sed s/" "//g)
getLocationWeather $args || exit 1
elif [[ $1 == "M" ]]; then
getIPWeather "?M" || exit 1
elif [[ "${@: -1}" == "M" ]];then
args=$( echo "${@:1:(($# - 1))}" ?M | sed s/" "//g)
getLocationWeather $args || exit 1
elif [[ $1 == "mM" || $1 == "Mm" ]]; then
getIPWeather "?m?M" || exit 1
elif [[ "${@: -1}" == "mM" || "${@:-1}" == "Mm" ]];then
args=$( echo "${@:1:(($# - 1))}" ?m?M | sed s/" "//g)
getLocationWeather $args || exit 1
elif [[ $1 == "iM" || $1 == "Mi" ]]; then
getIPWeather "?u?M" || exit 1
elif [[ "${@: -1}" == "iM" || "${@:-1}" == "Mi" ]];then
args=$( echo "${@:1:(($# - 1))}" ?u?M | sed s/" "//g)
getLocationWeather $args || exit 1
elif [[ $1 == "i" ]]; then
getIPWeather "?u" || exit 1
elif [[ "${@: -1}" == "i" ]];then
args=$( echo "${@:1:(($# - 1))}" ?u | sed s/" "//g)
getLocationWeather $args || exit 1
else
getLocationWeather "$@" || exit 1
fi

#--- ------------------------------------------------------------End of weather script ------------------------------------------------------------------------

Now I hear you say this is a useful script but first I have to open a terminal, type weather Sydney and then the terminal is not big enough to display all of the information so I have to adjust it. Wouldn't it be better if I could just click an icon on the desktop? Yes you can.

Create a wrapper script and call weather2. The main script can be called anything you want but lets call it weather.

The contents of weather2 should be:

------------------------------ Cut -------------------------------
#!/bin/sh
urxvt -g 150x50 -hold -e weather Sydney
------------------------------- Cut -------------------------------

Lets look at what the wrapper script does. First it opens a terminal 150 characters wide by 50 characters high. The -hold switch instructs the terminal to remain open until closed. The -e executes the main script called weather and instructs it to load the weather information for Sydney.

The weather2 script needs to be in a bin directory so place it along side weather in /usr/local/bin.

To place weather2 on the desktop simply drag and drop it there with your mouse, left-click drag and release. Once on your desktop you can right-click on the script, select File 'weather2' > Set Icon. Now drag an icon onto the dialog where it says Drop an icon file here.

Tips & Tricks

Tips & Tricks are simple little actions you can take to make your life easier when using Puppy. You will probably know most of the tips but there are always new users that don't.

Symlinks - smokey01
which command - smokey01

Symlinks

Written by smokey01

If you're new to Linux you may not be aware of the term symlink. Symlink is short for Symbolic Link. From the Wikipedia:

In computing, a symbolic link (also symlink or soft link) is the nickname for any file that contains a reference to another file or directory in the form of an absolute or relative path and that affects pathname resolution.

Symlinks are truly wonderful things and have many uses. Some applications expect to find their associated files in a particular location. If this location is in /root then you might find your savefile will fill up very quickly. It's better to store all of your data outside of the savefile or on another drive. If you simply move the data to another location then we need to tell the application where it has been moved to. Some applications have a preference area where you can define the data path and some don't.

OK, lets looks at a reasonably typical situation. The application is in /usr/bin. It expects to find it's data in /root/data. We don't want the data in /root/data so we move it to /mnt/home/data which is outside of the save file. Now we create a symlink called data in /root. This symlink points to /mnt/home/data. Now when the application needs to read or write to /root/data the symlink simply redirects to to the correct location in /mnt/home/data and everything is happy.

Hopefully by now you understand what a symlink is and does, but how do I make one? Let's do it the easy way with rox, our default File Manager.

Open two instances of rox. In one navigate to /root/ and in the other to /mnt/home. Now drag the data folder from /root to /mnt/home in the other Rox. When you release the left mouse button, choose move and the data folder will be relocated from /root to /mnt/home. Now to make the symlink. This time we are going to drag the data folder from /mnt/home back to /root. Sounds familiar doesn't it? Except this time we will select Link instead of move. Ah, but there are more than one link options. I usually select Link (relative). That's it the job is done and you have made a symlink. Notice the symlinked folder has an arrow on it!

You can make symlinks for files just the same. Maybe in the past your file manager was call fm instead of rox. Simply make a symlink of rox and call it fm. Now when you click on fm, rox will run. I hear you say why not just rename the file from rox to fm? There may be many other actions and applications that need a file called rox so you might break things. By creating a symlink to rox, you can have your cake and eat it too.

Which command

Written by smokey01

Quite often it's neccesary to locate a binary or a script in your system and fortunately there is an easy way to do this. In a terminal type which binary/script. EG: which geany.
The output will show the pathname. This is the path and binary/script name like: /usr/bin/geany

If you type echo $PATH into a terminal you get the following output: /usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/qt5/bin
This may be different in your Operating System but these are the paths which will search for your binary or script.

I often wondered why the command is called which instead of where or whereis. If you prefer to use the name where instead of which, simply make a symlink called where to which. First make sure there is no command called where: type where into a terminal. If the result is command not found you can use it without breaking anything. Now lets look for the which command, which which in a terminal and you should get a pathname EG: /usr/bin/which

Now we will make the symlink. ln -s /path/to/file /path/to/symlink

Type the following in a terminal: ln -s /usr/bin/which /usr/bin/where

Now you can type which or where to find binaries or scripts and have learned how to make a symlink from the terminal/command line interface (cli).

Good hunting.

Entertainment

The February crossword by greengeek.

Crossword

Puppy Crossword (February 2018)
(Formatted by greengeek using the "Puzzlefast" website)

"Real puppies"

We know lots about the huge range of puppies that we run on our computers,
but how much do we know about real breeds of puppies? See if you can work out the
names of some of these more esoteric dog breeds:

(See clues below image)











Scroll further down for answers:








Useful Links

Puppy Linux Forums USA

Ibiblio repository USA

nluug repository Netherlands

Internode repository Australia

University of Crete repository Greece

aarnet repository Australia

Internet archive repository USA

Puppy Linux Tips by smokey01

Puppy Linux wikka Puppy sites

Bookmarkos provided by kerl

Search the Puppy Linux Forums

Barry Kauler's News Blog

labbe5 Report

Contributors this month

Not all of the people below have physically given me the information to publish. If I find information I will give the credit where it is due. So if you see your name on the list below please don't be alarmed or upset. You are not losing your mind.

smokey01
greengeek
6502coder
Sailor Enceladus
fredx181
Alexander Epstein

Proof reading - russoodle

Newsletter Information

Display tip:
To improve the Notecase display format please press F7 then:
- Tick the "Restore last position/size" checkbox.
- Select the "Display" tab and tick "Wrap text".

Newsletter index written by 6502coder can be found here:
http://www.murga-linux.com/puppy/viewtopic.php?p=945962#945962

Contributions

If you have information you would like to see in the newsletter please email it to smokey01 at smokey01@internode.on.net. I prefer it to be created in Notecase otherwise it makes my job a bit more difficult. I don't intend doing any significant editing but I will attempt to read all of the articles and ask a couple of others to do some proof reading. If you would like to assist in proof reading please let me know on the email address above.

Notecase is very easy to learn and use. Try and keep your articles to less than 1000 words. Photos and images should be no bigger than 1024 x 768. I can always make them smaller.

The deadline for articles is the 20th of each month. Let's not worry about time zones. I know it may be the 20th in Australia and only the 19th in the USA but I can live with this. If it's more than 24 hours late with respect to Australian CST then your article may be pushed right, into the next edition. I expect proof reading to take less than a week which will provide about four days to publish at the beginning of each month.

I will upload the Newsletter to my site at http://smokey01.com/newsletters. There will be two versions. One will be an xz compressed Notecase file and the other will be a html file so it can be read in a browser.

I have changed the original naming convention to 0001-PuppyLinuxNewsletter-Jan2017.ncd.xz and 0001-PuppyLinuxNewsletter-Jan2017.html respectively. The formatting of the html is not brilliant but readable. The newsletter is intended to be downloaded and read in Notecase.

Disclaimer

The editor has the right to veto any articles that he/she considers inappropriate. A reasonable effort will be made to avoid spelling and grammatical errors however, I'm sure some may slip through. This newsletter is published by volunteers, and is free, so please be kind. Constructive criticism and positive suggestions are welcomed.

smokey01