Tips & Tricks for Technologists & System Administrators | About & Contact

Category: Software


SSH – Unspecified GSS failure

Posted 10th September in CentOS, Linux, Shell, System Administration. No Comments

Recently came across a problem with one system authentication to another via ssh.

I added the public ssh key to ~/.ssh/authorized_keys entry. Changed ownership to the proper user and also chmod 600 ~/.ssh/authorized_keys. Still no dice.

Using ssh -vvvv the following error returned on pubkey authentication:

1
2
debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

Well, that is pretty non-specific.

Since permission problems are the number one issue I have with getting ssh authentication working, and how I thought I set permissions right, my mind then wondered if SELinux permissions were causing a problem. Most providers disable SELinux right off the bat because of the ‘problems’ it causes, but some don’t. It turned out, this one has SELINUX=enforcing. So, let’s fix the SELinux permissions:

1
/sbin/restorecon -r /root/.ssh

This sets the context as follows:

1
2
# ls -Z authorized_keys
-rw-------. root root unconfined_u:object_r:ssh_home_t:s0 authorized_keys

SSH should now authenticate.


Enable/Disable Output of Audio Input in Ubuntu

Posted 3rd September in Ubuntu. 2 Comments

After hooking up my old-school turntable to the input jack on my desktop PC, I thought I’d be easily able to output the sound from my speakers. I could even see the audio playing as an input and could record it using Audacity, but not output it directly.

By default Ubuntu does not load the loopback module for Pulse, the audio manager for Ubuntu. You need to load this module to get the input audio to play out to your speakers. To enable this feature run the following command:

1
pactl unload-module module-loopback

This will load it one time, and when you reboot it will again be unloaded. To make it ‘stick’ and load on every boot, run this command:

1
sudo sh -c 'echo "load-module module-loopback" >>  /etc/pulse/default.pa'

If you want to undo the loopback module, run this command:

1
pactl unload-module module-loopback

and to disable it from running on startup:

1
sudo sh -c 'sed -i "/load-module module-loopback/d" /etc/pulse/default.pa'

This was tested in Ubuntu 13.04.

If you start getting weird audio feedback after running this command, you might want to check that you didn’t accidentally load the loopback adapter twice!


Simple Guide To Signing RPMs with FPM

I’ve been using the excellent fpm (Effing package manager!) tool for automatically generating rpms from source (for example, creating a custom compiled php-fpm binary and then wrapping it for install in an rpm for distribution from our own repository). FPM also creates .debs and other binaries as you need them.

To ensure we have a secure infrastructure we wanted to make sure that the rpms are correctly signed so that the gpg check can be completed on them when installed.

First, generate the gpg public/private key pair:

1
gpg --gen-key

Fill out the required information. The entropy generation step may take a long time to complete.

Export a text version of the public key with this command, for later use in your repository:

1
gpg --export -a 'Dave Drager' > ~/RPM-GPG-KEY-reponame

fpm docs state that you just need to add the –rpm-sign to your fpm command. However, this generated the following error for me:

1
2
error: You must set "%_gpg_name" in your macro file {:level=>:error}
Pass phrase check failed {:level=>:error}

The reason for this is that it uses the settings located in your ~/.rpmmacros file. Find your key ID:

1
2
3
4
5
6
# gpg --list-keys
/user/.gnupg/pubring.gpg
------------------------
pub   2048R/94E8C1F6 2013-04-24
uid                  Dave Drager <ddrager@xxx>
sub   2048R/94E8C1F6 2013-04-24

In this sample, the KEY_ID would be “94E8C1F6″

1
2
3
4
%_signature gpg
%_gpg_path /path/to/.gnupg
%_gpg_name KEY_ID
%_gpgbin /usr/bin/gpg

From here, the fpm command runs without issue.

1
2
3
4
# fpm -s dir -t rpm -n php-fpm-xda -v 5.2.23 -C /tmp/installdir -p php-fpm-xda_VERSION_ARCH.rpm -d openssl -d pcre -d bzip2 -d curl -d libjpeg -d libpng -d freetype -d gmp -d libmcrypt -d libmhash -d libxml2 --rpm-sign usr/bin usr/share/man/man1 usr/sbin etc usr/share/man/man8 usr/share/fpm usr/lib/build usr/include/php
Enter pass phrase:
Pass phrase is good. {:level=>:error}
Created rpm {:path=>"php-fpm-xda_5.2.23_x86_64.rpm"}

This is an alias of the rpm --addsign command.

Now let’s check the signature on this rpm.

1
2
# rpm --checksig php-fpm-xda_5.2.23_x86_64.rpm
php-fpm-xda_5.2.23_x86_64.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#94E8C1F6)

Whoops, it doesn’t seem to be signed properly. Well, that is because the rpm system doesn’t know to trust this GPG key yet. Import with the following command:

1
rpm --import ~/RPM-GPG-KEY-reponame

Note that this is the plain text file from before. Your RPM system knows to trust this key, and now if you verify the file:

1
2
# rpm --checksig php-fpm-xda_5.2.23_x86_64.rpm
php-fpm-xda_5.2.23_x86_64.rpm: rsa sha1 (md5) pgp md5 OK

This RPM is now ready for use in a repo. In the .repo file, use the following to ensure it follows the correct signature:

1
2
gpgcheck=1
gpgkey=http://repo.xxxx.com/RPM-GPG-KEY-reponame

All key names have been changed to protect the innocent.


How We Defeated a Proxy Jacker (Google Web Spam Syndrome)

Posted 31st August in Google, JavaScript, Other Technology. 2 Comments

A few months ago, we had an interesting issue with another website stealing our content in an unusual way. Essentially they ran a proxy service on a similar domain (a .com.ar instead of .com) and then replicated our site, replacing our ads with their own. They also ran our content through a content replacement algorithm, removing certain pieces of text and also replacing our own domain with theirs. It is fairly easy to do.

We had a few concerns about this. Firstly, we were worried that unsuspecting users would enter their login information on this site. Also, they actually were showing up in Google search engine results, which both hurts our brand, ranking and perception by users (this site loaded much slower than ours obviously).

First Attempt To Stop The Proxy Spammers: IP Blocking

Determined to put a stop to it, the first method we tried was blocking their crawler IPs. However, they owned enough IPs in enough ranges that it was simply a cat and mouse game. We would block them, and then a day later they would be back up. After a few weeks of this it didn’t seem to be a viable long-term solution for blocking these spammers.

Next, We Used Their Mirroring Of Our Content Against Them

Next I thought I would use the fact that they were modifying our page content and disable their site that way.

I created a box in html/css which would trigger via JavaScript only when loading from their domain. But, you wouldn’t think it would be that easy would you? They replace our domain with theirs, modifying any mention of their own domain. So I used a quick hash function to create a unique identifier from the loaded domain and then matched against that.

Also, figuring they would just take out the HTML box I created, I also found it useful to display a hex-encoded version of it. You can encode text to the hex-escaped version for Javascript with the following command line:

1
echo -n "some text" | od -A n -t x1 |sed 's/ /\\x/g'

The final Javascript I started loading on our site (and therefore their site) is below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script type="text/javascript">
jQuery(document).ready(function() {
  // From http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
  String.prototype.hashCode = function(){
    var hash = 0;
    if (this.length == 0) return hash;
    for (i = 0; i < this.length; i++) {
        char = this.charCodeAt(i);
        hash = ((hash<<5)-hash)+char;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
  }
  // sets hash to current domain
  domainhash = document.domain.hashCode();
  // lists domains they are loading the site from (calculate hash of the attacker domain first)
  if (domainhash == '-1289333690' || domainhash == '208666227') {
    var overlay_orig = jQuery('<div style="position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: #000;filter:alpha(opacity=50);-moz-opacity:0.5;-khtml-opacity: 0.5;opacity: 0.5;z-index: 999;text-align:middle;"></div><div style="position: fixed; top: 0px; width: 100%; z-index: 10000;"><div style="z-index: 10000; width: 400px; padding: 30px; margin: 200px auto; background-color: white; border: 1px solid black;color: black;"><h1 style="color:red">Warning: This Is A Scam Site</h1><p>Sorry for the interruption, but the site you are currently visiting is not the real one. This site scrapes our content and injects their own ads to make money./div></div>');
    // Hex encoded version of above, used to defeat content replacement
    var overlay = jQuery("\x3c\x64\x69\x76\x20\x73\x74\x79\x6c\x65\x3d\x22\x70\x6f\x73\x69\x74\x69\x6f\x6e\x3a\x20\x66\x69\x78\x65\x64\x3b\x74\x6f\x70\x3a\x20\x30\x3b\x6c\x65\x66\x74\x3a\x20\x30\x3b\x77\x69\x64\x74\x68\x3a\x20\x31\x30\x30\x25\x3b\x68\x65\x69\x67\x68\x74\x3a\x20\x31\x30\x30\x25\x3b\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x30\x30\x30\x3b\x66\x69\x6c\x74\x65\x72\x3a\x61\x6c\x70\x68\x61\x28\x6f\x70\x61\x63\x69\x74\x79\x3d\x35\x30\x29\x3b\x2d\x6d\x6f\x7a\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x2e\x35\x3b\x2d\x6b\x68\x74\x6d\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x20\x30\x2e\x35\x3b\x6f\x70\x61\x63\x69\x74\x79\x3a\x20\x30\x2e\x35\x3b\x7a\x2d\x69\x6e\x64\x65\x78\x3a\x20\x39\x39\x39\x3b\x74\x65\x78\x74\x2d\x61\x6c\x69\x67\x6e\x3a\x6d\x69\x64\x64\x6c\x65\x3b\x22\x3e\x3c\x2f\x64\x69\x76\x3e\x3c\x64\x69\x76\x20\x73\x74\x79\x6c\x65\x3d\x22\x70\x6f\x73\x69\x74\x69\x6f\x6e\x3a\x20\x66\x69\x78\x65\x64\x3b\x20\x74\x6f\x70\x3a\x20\x30\x70\x78\x3b\x20\x77\x69\x64\x74\x68\x3a\x20\x31\x30\x30\x25\x3b\x20\x7a\x2d\x69\x6e\x64\x65\x78\x3a\x20\x31\x30\x30\x30\x30\x3b\x22\x3e\x3c\x64\x69\x76\x20\x73\x74\x79\x6c\x65\x3d\x22\x7a\x2d\x69\x6e\x64\x65\x78\x3a\x20\x31\x30\x30\x30\x30\x3b\x20\x77\x69\x64\x74\x68\x3a\x20\x34\x30\x30\x70\x78\x3b\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\x33\x30\x70\x78\x3b\x20\x6d\x61\x72\x67\x69\x6e\x3a\x20\x32\x30\x30\x70\x78\x20\x61\x75\x74\x6f\x3b\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x77\x68\x69\x74\x65\x3b\x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x31\x70\x78\x20\x73\x6f\x6c\x69\x64\x20\x62\x6c\x61\x63\x6b\x3b\x63\x6f\x6c\x6f\x72\x3a\x20\x62\x6c\x61\x63\x6b\x3b\x22\x3e\x3c\x68\x31\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x72\x65\x64\x22\x3e\x57\x61\x72\x6e\x69\x6e\x67\x3a\x20\x54\x68\x69\x73\x20\x49\x73\x20\x41\x20\x53\x63\x61\x6d\x20\x53\x69\x74\x65\x3c\x2f\x68\x31\x3e\x3c\x70\x3e\x53\x6f\x72\x72\x79\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x69\x6e\x74\x65\x72\x72\x75\x70\x74\x69\x6f\x6e\x2c\x20\x62\x75\x74\x20\x74\x68\x65\x20\x73\x69\x74\x65\x20\x79\x6f\x75\x20\x61\x72\x65\x20\x63\x75\x72\x72\x65\x6e\x74\x6c\x79\x20\x76\x69\x73\x69\x74\x69\x6e\x67\x20\x69\x73\x20\x6e\x6f\x74\x20\x74\x68\x65\x20\x72\x65\x61\x6c\x20\x6f\x6e\x65\x2e\x20\x54\x68\x69\x73\x20\x73\x69\x74\x65\x20\x73\x63\x72\x61\x70\x65\x73\x20\x6f\x75\x72\x20\x63\x6f\x6e\x74\x65\x6e\x74\x20\x61\x6e\x64\x20\x69\x6e\x6a\x65\x63\x74\x73\x20\x74\x68\x65\x69\x72\x20\x6f\x77\x6e\x20\x61\x64\x73\x20\x74\x6f\x20\x6d\x61\x6b\x65\x20\x6d\x6f\x6e\x65\x79\x2e\x2f\x64\x69\x76\x3e\x3c\x2f\x64\x69\x76\x3e
"
);
    overlay.appendTo(document.body);
  }
});
</script>

After thoroughly testing and then putting up the code, we launched it live. It was very satisfying knowing that end-users were getting the warning message when visiting their site, and the actually reported their experience back to us. After about 12 hours, they figured out our play out and turned off their proxy. Success!

Not quite. The next morning I woke up to see their site back up. Looking into their code, they had removed the JS completely. I changed our code, embedded it in a JS file, and used other creative means to get it back up – but in the end they were just able to disable the Javascript entirely and defeat this attack. It was just another cat-and-mouse game.

We also tried DMCA/Abuse Contacts

We also tried to send notices to their hosting company to get them to take down the site. They were hosted in Argentina, so DMCA is not applicable. Their abuse contacts were non-responsive.

Originally we thought we could go after their domain registration since it violated our trademark – but this is a long and involved process involving lots of paperwork and time, and for another $10 they could just register another domain name. We didn’t think this was a viable option.

Going to the Source: Google

Google is involved in this scam in a number of ways. First, they were indexing and serving his site in their search results. Secondly the scammers were replacing our ads with their own Google AdSense ads, which I am sure is a ToS violation.

While we were attempting to defeat their site from a technical perspective, we also began looking at Google to see what we could do from there.

Google has a process for submitting DMCA requests. The issue in this case is that they make you submit one batch at a time, and with millions of pages on our site and indexed in Google, it just doesn’t make sense to list out urls line by line. It worked to remove those submitted results from search engine results, but it was like cutting grass with scissors. Finally, I attempted to contact Matt Cutts via Twitter:



Thanks. So much for that venue. I know @mattcutts is the public face of Web Spam at Google so I’m sure that he gets lots of @’s with dumb questions, but we were already way beyond this.

Finally, What Worked

Members of our site had a few personal contacts at Google both in an AdSense representative and otherwise. One of our contacts with Google was able to bring this issue up with the right people and they finally took the offending domain out of the SERPs permanently. We also reported their AdSense account – but we don’t know what happened with that. Without them showing up in SERPs, it was a moot point because they won’t be getting many visitors any more.

The Problem With Google

Google has become so large that it is almost impossible to get a situation like this taken care of without knowing someone who works for them. They have many automated systems in place, but scammers will continue to utilize loopholes for their own profit. Google enables this type of scam, yet they also profit from it.

I wish Google would have some sort of Ombudsman or review system set up so that someone like us, who is having our content ripped off by others using Google’s own tools (and with Google taking a percentage of profit from these people), has a way to efficiently deal with them without resorting to personal contacts. We spent much time on this, time that could have been put to better use.

Or maybe personal contacts are the only real way to deal with a situation like this?

Anyway – I am welcoming comments and any other ideas for dealing with these Proxy Hijackers and how to keep them offline. I’m curious how widespread this type of incident is, we know of only one other site that was having the same issue from the same scammer.

After all, they can always get another domain for $10.


Evaluating FTP Servers: ProFTPd vs PureFTPd vs vsftpd

Usually, I will try to push clients towards using SCP (via a client such as WinSCP), however inevitably there are clients who do not understand this new method of accessing their files securely online, and who for one reason or another insist on using FTP for their online file access. As they say – the customer is always right?

Anyway, there are currently 3 mainstream FTP servers available via the yum command on CentOS 6.x. PureFTPd, ProFTPd and vsftpd. So which FTP server is the best? I will summarize the servers below, or skip to the summary.

ProFTPd

ProFTPd is a modular FTP server which has been around for a long time. The large control panels (cPanel, DirectAdmin) all support ProFTPd and have for years.

The most feature rich of the bunch is certainly ProFTPd. There are a ton of plugins available for it, and the creator of it modeled its configuration architecture much like Apache’s – it is also using the GPL for licensing.

Configuration of ProFTPd is fairly straight forward, and example configuration files abound at a quick search of Google.

ProFTPd is available on a wide variety of system architectures and operating systems.

ProFTPd Security

Of the bunch, ProFTPd has the most CVE vulnerabilities listed. The high number is most likely an indicator of ProFTPd’s widespread use which makes it a target of hackers.

ProFTPd CVE Entries: 40
Shodan ProFTPd entries: 127

PureFTPd

PureFTPd‘s mantra is ‘Security First.’ This is evident in the low number of CVE entries (see below).

Licensed under the BSD license, PureFTPd is also available on a wide-range of operating systems (but not Windows).

Configuration of PureFTPd is simple, with a no-configuration file option. Although not as widely used as ProFTPd, PureFTPd has many configuration examples listed online.

PureFTPd Security

PureFTPd’s “Security First” mantra puts it at the lead in the security department with the fewest security vulnerabilities.

PureFTPd CVE Entries: 4
Shodan Pure-FTPd Entries: 12

vsftpd

vsftpd is another GPL-licensed FTP server, which stands for “Very Security FTP daemon.” It is a lighweight FTP server built with security in mind.

Its lightweight nature allows it to scale very efficiently, and many large sites (ftp.redhat.com, ftp.debian.org, ftp.freebsd.org) currently utilize vsftpd as their FTP server of choice.

vsftpd Security

vsftpd has a lower number of vulnerabilities listed in CVE than ProFTPd but more than PureFTPd. This could be because, since its name implies it is a secure FTP service, or because it is so widely used on large sites – that it is under more scrutiny than the others.

vsftpd CVE Entries: 12
Shodan vsftpd entries: 41

Summary & FTP Server Recommendations

#

Considering the evaluations above, any server would work in a situation, however generally speaking:

  • If you want a server with the most flexible configuration options and external modules: ProFTPd
  • If you have just a few users and want a simple, secure FTP server: PureFTPd
  • If you want to run a FTP server at scale with many users: vsftpd

Of course, everyone’s requirements are different so make sure you evaluate the options according to your own needs.

Disagree with my assessment? Let me know why!


Xbox 360 Windows Media Center Extender Demo

Posted 12th January in Gaming, Other Technology, Software, Television. Comments Off

After I ditched cable TV, I used both Snapstream’s BeyondTV and SageTV (now owned by Google) to sate my and my family’s television needs. After almost 2 years we ended up turning cable back on. Win one for the cable company!

But that did not end my search for the perfect home television system. Our cable box, well, works; but the hard drive is limited, you have to pay $15.99/mo for it, and the recordings are only on one device.

Luckily I found the DCR-2650 (currently $122 at amazon) which allows you to rent a CableCARD from the cable company (I’m paying $3.99/mo from Verizon) and get all of the premium cable channels on your PC – the drawback is that you must use Windows Media Center due to the DRM (there is a hack for SageTV – more on that later).

We recently got an Xbox 360 for Christmas, and I’ve been wanting to try the Media Center Extender functionality on it. I’m happy to report it works really well! Here is a video with a quick walkthrough of the Media Center Extender experience on the Xbox 360.

Some notes on the setup:

  • My Media Center PC & Xbox are both connected via gigabit wired network
  • Live TV, Guide and DVR functionality work perfectly
  • Have had issues with Movie playback. This is because the Xbox is limited in what codecs it can decode. Apparently the Windows Media Center Extender app does not use the same codecs as the Xbox media player app.
  • You could use as many Xboxes as you want, so essentially you have a free number of DVRs in your home
  • The DCR-2650 uses a single cable card but has 2 tuners. This means you are limited to 2 channels at a time of live TV or recording shows. You could easily continue to add tuners if you would like more.
  • The Windows Media Center app is available directly on the main Xbox menu that pops up when you hit the Xbox button on your controller/remote

The quality of the video coming from the Media Center Extender is significantly better compared to the “LiveTV” streamed over the internet – also from Verizon.

If Microsoft and Verizon is serious about making their streaming live TV app commonplace in consumer’s homes, they will need to both up the quality of the video and also add DVR functionality to the system.

Between how well it works and the fact that you can get a remote for the Xbox, it really makes an ideal replacement for your cable box.


Experimenting with Pascal on Ubuntu

Posted 21st February in Code Samples, Other Code, Ubuntu. Comments Off

I’ve been busy lately on a number of projects, one of which is a programming class I am currently taking. The class itself is interesting, we are learning about the different types of programming languages. For our latest project, we were tasked with writing a simple program in Pascal. Pascal isn’t used too much any more since it lacks some of the features that most modern languages have, but it is good to know at least a little bit about it in case you ever run across some old Pascal programs in the wild.

The syntax for pascal is a bit verbose, that is the main complaint about it. There are a number of others, but that is beyond the scope of this howto.

Installing The Pascal Compiler on Ubuntu

Installing Pascal in modern Ubuntu is a cinch. The Free Pascal Compiler, or fpc, is all that you need to get started. It works great on 32-bit or 64-bit systems. Install with:

1
sudo apt-get install fpc

Any prerequisites will automatically download and install along with fpc.

Getting Started in Pascal

To test the compiler let’s start with a simple Hello World program. Open up hello.pas and enter:

1
2
3
4
5
6
7
program Hello;

begin

Writeln('Hello World');

end.

Compile with fpc hello.pas and run:

1
2
dave@cerberus:~/Pascal$ ./hello
Hello World

Selection Sort in Pascal

Now that we’ve verified it is running, I’m going to show you the code that I wrote for my program. Basically we were asked to Selection Sort two arrays of varying length. Apparently one of the (bad) features of Pascal originally was that you needed to declare the length of the array which made it a pain to work with them.

In this situation it is just two arrays so it isn’t too bad. Enter your array by creating two text files arrayA.txt and arrayB.txt. One number per line. The source code for sort.pas is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
program Sort;

var
        A: array[1..10] of Integer;
        B: array[1..20] of Integer;
        F: Text;
        i,j,k,l,m,temp: Integer;

begin
        {Read in array A}
        Assign(F, 'arrayA.txt');
        Reset(F);
        i:= 0;
        while not EOF(F) do begin
                Inc(i);
                Read(F, A[i]);
        end;

        {Read in array B}
        Assign(F, 'arrayB.txt');
        Reset(F);
        j:= 0;
        while not EOF(F) do begin
                Inc(j);
                Read(F, B[j]);
        end;
        i:=10;
        j:=20;

        {Print out the unsorted arrays}
        WriteLn('Unsorted Arrays:');
        WriteLn('Array A:');
        for k:=1 to i do
        Write(A[k], ' ');
        WriteLn();
        WriteLn('Array B:');
        for k:=1 to j do
        Write(B[k], ' ');
        WriteLn();
        WriteLn('=========================');
        WriteLn('Sorting Arrays...');
        WriteLn('=========================');

        {Selection Sort Array A}
        for l := 1 to i do
                for m := l + 1 to i do
                        if A[l] > A[m] then
                        begin
                                temp := A[l];
                                A[l] := A[m];
                                A[m] := temp;
                        end;
        {Selection Sort Array B}
        for l := 1 to j do
                for m := l + 1 to j do
                        if B[l] > B[m] then
                        begin
                                temp := B[l];
                                B[l] := B[m];
                                B[m] := temp;
                        end;

        {Print out the sorted arrays}
        WriteLn('Selection Sorted Arrays:');
        WriteLn('Array A: ');
        for k:=1 to i do
        Write(A[k], ' ');
        WriteLn();
        WriteLn('Array B: ');
        for k:=1 to j do
        Write(B[k], ' ');
        WriteLn();
end.

Compile and run (ok to ignore the compile-time errors)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dave@cerberus:~/Pascal$ fpc sort.pas
Free Pascal Compiler version 2.4.0-2 [2010/03/06] for x86_64
Copyright (c) 1993-2009 by Florian Klaempfl
Target OS: Linux for x86-64
Compiling sort.pas
Linking sort
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
73 lines compiled, 0.1 sec
dave@cerberus:~/Pascal$ ./sort
Unsorted Arrays:
Array A:
28 24 85 55 43 6 23 13 59 71
Array B:
13 37 36 53 24 83 27 42 62 71 9 92 1 41 6 3 88 77 65 67
=========================
Sorting Arrays...
=========================
Selection Sorted Arrays:
Array A:
6 13 23 24 28 43 55 59 71 85
Array B:
1 3 6 9 13 24 27 36 37 41 42 53 62 65 67 71 77 83 88 92
dave@cerberus:~/Pascal$

And there you have it. Compiling Pascal program on Ubuntu is an easy way to get your feet wet in programming. Pascal is a great beginner’s programming language, but if you want to learn more there are a number of great resources available for learning Pascal.