Raam Dev’s Weblog

Avatar

A man without scars has not lived his life to the fullest.

My C Program Crashed the Terminal :(

As part of my homework assignment (due tonight!), I have to write two versions of the standard library function strncpy(), one using array’s and one using pointers.

The strncpy() function basically takes two arguments, *src and *dest, and copies n number of bytes from *src to *dest.

#include <string.h>

// Function declarations
char *mystrncpy(char *dest, const char *src, size_t n);

main()
{
    char a[] = "this is a string";
    char b[50];

    mystrncpy(b, a, 400); // here is the problem
    printf("%s\n", b);

    return 0;
}

// My attempt to replicate the strncpy() function with pointers
char *mystrncpy(char *dest, const char *src, size_t n)
{
    int i = 0;
    while (i <= n) {
        *dest = *src;
        src++;
        dest++;
        i++;
    }
}

While testing this pointer version of the function, I passed a much larger size (400) to the function than had been allocated for the destination variable (b[50]).


eris:hw3 raam$ gcc problem8.c -o problem8
eris:hw3 raam$ ./problem8
this is a string
Segmentation fault

Segmentation Fault

There is no better way to tell me my function needs more work than to stick a big “Application quit unexpectedly” message in my face! (And thankfully, my entire iTerm app did not crash.)

I wrote a post a few weeks ago about how eerily close C variables are to the machine, and the way this program crashed further confirms that point. I can’t imagine the kinds of nasty things I will be able to do once I learn more advanced C functions. :D

C Variables: Eerily Close to the Machine

In C programming, things as simple as variable assignment are not quite as simple as using an assignment operator—they sometimes require entire functions. For example, this code will not even compile:

#include        <stdio.h>
#include        <strings.h>

int main()
{
        char    a[10], b[10];

        a = "hello";
        b = "world!";

        printf("%s %s", a, b);

        return 0;
}


$ cc test.c
test.c: In function ‘main’:
test.c:8: error: incompatible types in assignment
test.c:9: error: incompatible types in assignment

In C all strings are arrays. To create a string variable, you must create an array. The variable “a” is actually a pointer to the memory location of the character array, not the contents of the array itself! That’s why I got the “incompatible types in assignment” error when I tried compiling the above code—I was trying to copy a string directly into a memory address!

The reason things are this way in C is for speed and simplicity. Sure, other languages automatically do the work of putting your five-character string into a variable and automatically allocate the necessary space in memory, but by doing that they spend a little more time behind the scenes—time and speed that may be precious to a systems-level programmer (who might be writing a program for, say, a tiny embedded device).

To copy a string into an array (i.e., assign a string to a variable), you can use the strcpy() function. This function does the work of taking each character in your string and putting it into the correct place in the given array:

#include        <stdio.h>
#include        <strings.h>

int main()
{
        char    a[10], b[10];

        strcpy(a, "hello");
        strcpy(b, "world!");

        printf("%s %s", a, b);

        return 0;
}


$ cc test.c
$ ./a.out
hello world!

C was written in a time when assembly language was the norm. The problem with assembly language was that it was very tied to the hardware you were working on. Porting your work to other hardware, even if the changes in the hardware were only minor, required an entire rewrite of your code! Operating systems were also written in assembly at the time so creating a single operating system that worked on many different architectures was nearly impossible (unless you had an unlimited amount of time and money to have programmers constantly rewriting the operating system for every new hardware architecture that was released).

So the C programming language was created as a language one level higher than assembly. It was designed to maintain all the power and flexibility of assembly, while making it very easy to port to multiple architectures. This was made possible by using a compiler. The compiler simply took the C code and converted it into the necessary machine language for a specific architecture. If you wanted to port all your C code to a new architecture, all you needed to do was write a new compiler—not rewrite all your programs!

C lets you do stupid things not because it’s stupid, but because flexibility and closeness to the physical hardware is necessary for writing operating systems. (As the programmer, it’s your job to make sure what you’re doing is possible with the hardware you’re working on.) Where as other high-level languages will automatically take your string and stick it in the correct place in memory, C does only what you tell it to do. This makes it extremely fast, which is very important when you’re writing an operating system.

The basic example of how a string cannot be assigned directly to the character variable because the variable is actually a pointer to a memory address, helped me realize why C is still used for systems-level programming and why it continues to be in use more than 35 years after its invention. I have flipped through many C books but never quite gotten this explanation of how C works. Understanding things at this level really helps me put the language in perspective.

Escaping Filename or Directory Spaces for rsync

To rsync a file or directory that contains spaces, you must escape both the remote shell and the local shell. I tried doing one or the other and it never worked. Now I know that I need to do both!

So lets say I’m trying to rsync a remote directory with my local machine and the remote directory contains a space (oh so unfortunately common with Windows files). Here’s what the command should look like:

rsync 'raam@example.com:/path/with\ spaces/' /local/path/

The single quotes are used to escape the space for my local shell and the backslash is used to escape the remote shell.

  • I’ve been working day and night for the past few days on an already-late project for work. The fact that the project requires a computing language that was very unfamiliar to me just a few short weeks ago certainly adds to the brain drain. But, it’s a language I’ve been wishing I had a reason to learn for years now so I’m definitely not complaining! (0)

Making Checkboxes Behave like Radio Buttons

A while back I found the need to have HTML checkboxes behave like radio buttons. As you probably know, the main difference between the two is that multiple checkboxes can be selected at the same time whereas only one radio button can be selected at any given time (of course this changes depending on the context).

So how do you make checkboxes behave like radio buttons? With a bit of Javascript, it’s pretty easy:

<form name="formName">
<input type="checkbox" name="priorityHigh"
	onclick="if(this.checked) {document.formName.priorityLow.checked=false;}">High Priority

<input type="checkbox" name="priorityLow"
	onclick="if(this.checked) {document.formName.priorityHigh.checked=false;}">Low Priority
</form>

Here is what the form looks like:

High Priority

Low Priority

As you can see, only one checkbox can be selected at a time; the checkboxes are behaving like radio buttons! This solution allows you to leave both boxes unchecked, or check only one.

Fixing Boot-Time Dialog Display Issues

Dialog is a really useful utility for creating professional looking dialog boxes and menus within a shell script. I’m working on a boot-time script that allows the user to make system-level changes before the system has fully booted.

When testing my script from the command line, the dialog menu looked fine. However, whenever I set the script to start during boot (update-rc.d myscript.sh defaults, on Debian-based systems) here is what the menu looked like:

dialog display issues

UGH! It was barely usable. At first, I thought this would be an endlessly difficult problem to solve given my limited in-depth knowledge of Linux (I’m getting there!), but then I realized the main difference between the script running during boot and the script running after I had logged in was that my environment variables had not been loaded.

From the command line, I ran the env command to display all my current environment variables:

debian_vm:~# env
TERM=xterm-color
SHELL=/bin/bash
SSH_CLIENT=172.16.168.1 61315 22
SSH_TTY=/dev/pts/0
USER=root
MAIL=/var/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11
PWD=/root
LANG=en_US.UTF-8
PS1=\h:\w\$
SHLVL=1
HOME=/root
LANGUAGE=en_US:en_GB:en
LOGNAME=root
SSH_CONNECTION=172.16.168.1 61315 172.16.168.132 22
_=/usr/bin/env

The three variables that caught my eye were TERM, SHELL, and LANG. After a little trial and error, I discovered setting the LANG variable fixed the display issues with dialog! I added the following near the top of my script:

export LANG=en_US.UTF-8

Now when my script loads during boot, everything looks correct:

dialog display issues fixed

Multiple Query Problems with mysql_query()

I was writing some code earlier today that involved writing data to two separate MySQL tables. The second INSERT statement needed to contain the automatically generated ID (auto_increment) of the first INSERT statement, so I wanted all the queries to run one after another.

Thinking it made the most sense to just build one long query and execute it all at once, I wrote code similar to the following:

// Build a query with multiple INSERT statements
$q = "INSERT INTO sessions VALUES(NULL, '$name', '$desc', '$stime');";
$q .= "INSERT INTO events VALUES(LAST_INSERT_ID(), '$event', '$e_desc');";

// Execute query
mysql_query($q, $conn) or die(mysql_error());

Upon running the code I received this error:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '; INSERT INTO events VALUES(LAST_INSERT_ID(), '24', 'my event1', 'button')' at line 1

So, as I normally do when this kind of problem arises, I echoed the query that was being executed and, hoping to get more information on the error, I ran it directly from phpMyAdmin. Here is the SQL I ran:

INSERT INTO sessions
	VALUES(NULL, 'Raam', 'example', '2008-04-24 21:59:08');
INSERT INTO events
	VALUES(LAST_INSERT_ID(), '24', 'my event1', 'button');

phpMyAdmin says:

Your SQL query has been executed successfully

OK, so my SQL is fine.

I then looked up the mysql_query() function on php.net and found this little tidbit of info:

mysql_query() sends an unique query (multiple queries are not supported) to the currently active database on the server that’s associated with the specified link_identifier .

Ah, so multiple queries are not supported with the mysql_query() function. That’s most likely a security feature, but quite annoying none the less. The bottom line is, you cannot run multiple queries with mysql_query().

PHP5 has the mysqli_multi_query() function, which does allow you to run multiple queries (I know, I know, I should be coding for PHP5 by now).

Adding CC Recipients With PEAR Mail

I use the PEAR Mail package quite often in projects that require sending email — either user-generated or system-level notification emails. I recently wrote something at work that required CCing the user a copy of the email. My first thought was that simply adding CC headers with the users’ email address would suffice, but that just isn’t the case.

Since mail headers can be modified to state anything you want, PEAR Mail doesn’t actually use them to to figure out where to send the email (adding the CC header works fine and the users’ email address even shows up in the CC field, but they never receive the email).

A comment by Armin Frey that I found on the PEAR bug page for this problem explains what’s going on and offers a solution:

[2007-07-06 15:22 UTC] arminf (Armin Frey)

It seems that the Recipients decides where to send the e-mail and the
headers decide how to display it.

The simple solution is that you add all the addresses to $recipients.

Here is the code I used:

$to = 'to@example.com';
$cc = 'cc@example.com';
$recipients = $to.", ".$cc;
$headers['From']    = 'from@example.com';
$headers['To']      = $to;
$headers['Subject'] = 'Test message';
$headers['Cc']	    = 'cc@example.com';
$headers['Reply-To'] = 'from@example.com';

$send = $mail->send($recipients, $headers, $body);

The solution works perfectly. Now the email addresses show up in the correct fields and all the recipients receive the email. Unfortunately, this method does not work for BCCing users. I wonder if BCCing is even possible with PEAR Mail or if I’ll need to find something else. To Blind CC (aka, BCC) an address, simply add the address to the $recipients, but not to any of the $headers (thanks Jason!).

The Object-Oriented Thought Process

I started reading a book called The Object-Oriented Thought Process. This book has been sitting on my shelf for at least a year or two (there’s a 3rd Edition due out later this year) but with all the Java and GWT stuff I’m trying to become familiar with for work, I really feel the need to build a basic understanding of OO programming. This book is written for just that (and at only 250 pages, finishing the book quickly is not an unrealistic goal).

After finishing the first chapter earlier today, certain techniques I remember seeing used in Java (which didn’t make any sense to me at the time) suddenly make perfect sense. Not only that, but terms like “Encapsulation”, “Polymorphism”, and “Composition” suddenly mean something that I can now understand. All this from just the first chapter!

One of the main reasons I’m excited to gain a solid understanding of the Object-Oriented thought process is because it will allow me learn and use features of programming languages such as Python and Ruby without feeling as though I’m missing something or lacking the ability to use the features those languages are designed around.

Let’s see how many chapters I can finish this Memorial Day weekend!

Continuous Integration and PHP

Dabbling in Java Web Programming

A bunch of new projects at work are requiring that I become familiar with Java programming, web programming and GWT in particular. My co-worker gave me this tutorial to try out, as the principles are similar to what we’re using in the new projects.

So after setting up my environment (that’s another post), I followed the tutorial and then began modifying the example code to see how I could change it. (The first thing that surprised me was that Java doesn’t automatically sort stuff — you need to do that separately (that’s where SortedMap came in handy)):

package com.sonatype.maven.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SimpleServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException, NoSuchElementException {

		PrintWriter out = response.getWriter();
		out.println("SimpleServlet Executed");
		out.println("Character Encoding is " + response.getCharacterEncoding());
		out.println("ContentType is " + response.getContentType());

		out.println("\nHere is a list of all query string vars:\n");

		Enumeration e = request.getParameterNames();
		SortedMap sm = new TreeMap();

		while (e.hasMoreElements()) {
			String name = (String) e.nextElement();
			String value = request.getParameter(name);
			sm.put(name, value);
		}

		for (Iterator i = sm.entrySet().iterator(); i.hasNext();) {
			out.println(i.next());
		}

		out.println("\nHere are the vars combined into a sentence:\n");

		for (Iterator i = sm.values().iterator(); i.hasNext();) {
			out.print(i.next() + " ");
		}
		out.flush();
		out.close();
	}
}

So basically, after starting the Jetty Servlet container I was able to visit a URL like this:

http://localhost:8080/simple-webapp/simple?var1=Hello&var2=world&var3=of&var4=java!

And got an output like this:

SimpleServlet Executed
Character Encoding is ISO-8859-1
ContentType is null

Here is a list of all query string vars:
var1=Hello
var2=world
var3=of
var4=java!

Here are the vars combined into a sentence:

Hello world of java!

Java is cool stuff and I’m going to be diving into it a lot over the next few months. I’m reading an O’Reilly book called Head First Java which uses an innovative new method of teaching:

The latest research in cognitive science, neurobiology, and educational psychology shows that learning at the deeper levels takes a lot more than text on a page. Actively combining words and pictures not only helps in understanding the subject, but in remembering it. According to some studies, an engaging, entertaining, image-rich, conversational approach actually teaches the subject better. Head First Java puts these theories into practice with a vengeance. Chock full of mind stretching exercises, memorable analogies, and stories, humor and attitude that aren’t just pasted-on distractions but that are used to drive home key points and make ideas come alive, the Head First approach is as effective as it is unique.

The method is definitely new to me, but it makes a lot of sense. I’ve started committing an hour each day to reading the book and doing examples/puzzles.

Phing: Building with PHP

Amazon S3 HMAC Signatures without PEAR or PHP5

The Amazon S3 proposal for uploading via POST describes how to assemble a policy document that can be used to create a time-sensitive signature. The obvious advantage to this method is that you don’t have to worry about someone stealing your secret AWS key or uploading random files without your permission.

Here is the example policy document from the proposal:

{ "expiration": "2007-12-01T12:00:00.000Z",
  "conditions": [
    {"acl": "public-read" },
    {"bucket": "johnsmith" },
    ["starts-with", "$key", "user/eric/"],
    ["content-length-range", 2048, 20971520]
  ]
}

This Policy document is Base64 encoded and the Signature is the HMAC of the Base64 encoding.

The application I am developing at work requires this signed policy method of uploading files to S3, however I needed to do it with PHP4 and preferably without any extra PEAR packages. This posed somewhat of a challenge, as all the tutorials I found on the web explained how to sign the policy using the PEAR Crypt_HMAC package or some feature of PHP5.

I eventually figured it out, and I’m here to show you how. The two functions used were found on the web (I don’t remember exactly where) and worked perfectly for my situation.

(Note: I had a lot of trouble saving the contents of the following code in WordPress due to some Apache mod_security settings configured on my server.)

/*
 * Calculate HMAC-SHA1 according to RFC2104
 * See http://www.faqs.org/rfcs/rfc2104.html
 */
function hmacsha1($key,$data) {
    $blocksize=64;
    $hashfunc='sha1';
    if (strlen($key)>$blocksize)
        $key=pack('H*', $hashfunc($key));
    $key=str_pad($key,$blocksize,chr(0x00));
    $ipad=str_repeat(chr(0x36),$blocksize);
    $opad=str_repeat(chr(0x5c),$blocksize);
    $hmac = pack(
                'H*',$hashfunc(
                    ($key^$opad).pack(
                        'H*',$hashfunc(
                            ($key^$ipad).$data
                        )
                    )
                )
            );
    return bin2hex($hmac);
}

/*
 * Used to encode a field for Amazon Auth
 * (taken from the Amazon S3 PHP example library)
 */
function hex2b64($str)
{
    $raw = '';
    for ($i=0; $i < strlen($str); $i+=2)
    {
        $raw .= chr(hexdec(substr($str, $i, 2)));
    }
    return base64_encode($raw);
}

/* Create the Amazon S3 Policy that needs to be signed */
$policy = '{ "expiration": "2007-12-01T12:00:00.000Z",
  "conditions": [
    {"acl": "public-read" },
    {"bucket": "johnsmith" },
    ["starts-with", "$key", "user/eric/"],
    ["content-length-range", 2048, 20971520]
  ]';

/*
 * Base64 encode the Policy Document and then
 * create HMAC SHA-1 signature of the base64 encoded policy
 * using the secret key. Finally, encode it for Amazon Authentication.
 */
$base64_policy = base64_encode($policy);
$signature = hex2b64(hmacsha1($secretkey, $base64_policy));

That’s it! This method doesn’t require PHP5 and doesn’t require any additional PEAR packages.