Thursday, July 18, 2013

How to Code UNIX Daemons - Part One

In continuing with my time-honored tradition in bringing you the absolute latest in small code samples, here's an example of how to write a UNIX daemon. For the unfamiliar, daemons are background backgrounds that are typically started when the system starts up and have one specific task - typically ranging from serving web pages (the Apache web server, https, is a daemon, as is sshd, which listens for ssh requests on remote servers you can ssh into).

So, without further ado, here's the code sample:

 #include <unistd.h>  
 #include <fcntl.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <stdio.h>  
 #include <syslog.h>  
 #include <sys/types.h>  
 #include <sys/stat.h>  
 int main(int argc, char *argv[]) {  
   // Set our uid to root so we get root permissions.  
   setuid(0);  
   // Fork off.  
   pid_t pid;  
   int current_arg = 0;  
   pid = fork();  
   if (pid < 0) {  
     exit(EXIT_FAILURE);  
   }  
   if (pid > 0) {  
     exit(EXIT_SUCCESS);  
   }  
   umask(0);  
   // Open a syslog so we can post messages, as daemons shouldn't access  
   // stdout.  
   openlog(argv[current_arg], LOG_NOWAIT|LOG_PID, LOG_USER);  
   syslog(LOG_NOTICE, "Successfully started daemon\n");  
   // Create a new process group.  
   pid_t sid;  
   sid = setsid();  
   if (sid < 0) {  
     syslog(LOG_ERR, "Could not create process group\n");  
     exit(EXIT_FAILURE);  
   }  
   // Set our working directory to / so we know where we're writing files  
   // from. Also good practice.  
   if ((chdir("/")) < 0) {  
     syslog(LOG_ERR, "Could not change working directory to /\n");  
     exit(EXIT_FAILURE);  
   }  
   // Close the standard streams like stdout so we're not attached to the  
   // console (and thus killable with Control-C).  
   close(STDIN_FILENO);  
   close(STDOUT_FILENO);  
   close(STDERR_FILENO);  
   // Now mimic some daemon activity. A real daemon would actually do  
   // something here, such as monitor CPU temperature or something...  
   do {  
     syslog(LOG_NOTICE, "Sending a message\n");  
     sleep(10);  
   } while (1);  
   // Close our access to the syslog.  
   closelog();  
 }  

Put this into a text file, and then compile it with your C compiler. You then go into the terminal, run your program, and… it exits immediately - what gives?

The truth is, something did happen - you just don't notice. Thanks to our fork() call, we split off from the main process and run in the background.

In the second part of this series, we'll write a more complicated daemon program. See you later!

Sunday, July 7, 2013

Mac Linux USB Loader v1.1 Consumer Preview

For all of you wondering what the last month or so of coding has meant for Mac Linux USB Loader, you are in luck! I am, as of now, officially releasing a consumer preview of version 1.1 of Mac Linux USB Loader! You can download it here on SourceForge.

Version 1.1 is mainly a small release with bug fixes, but there is one important new feature that I'm beta testing right now: the automatic USB device blesser. On OS X, a drive can be "blessed" to instruct the firmware to boot it - it can be on any drive at any path, and not just at /efi/boot/. Mac Linux USB Loader uses this feature of Macs in an important new way: it allows your Mac to automatically boot your USB stick whenever it is plugged in - no more holding down the Option key is required.

This feature remains optional and can be accessed via a new option called Modify Boot Settings on the main panel:


After you click the Modify Boot Settings option, the following sheet will pop down:



Just select your USB drive that has an installation of a Linux distribution created by Mac Linux USB Loader, press the Bless button, enter your administrator password, and viola! - when you restart your Mac with the USB stick in the drive, it'll boot up automatically into your installed Linux distribution. Of course, the Unbless button does the exact opposite.

Again, if you want to try out this feature, you can download the preview here. Please note that this is an unstable release, and if something goes wrong, I assume no liability*.

* - Worst case scenario: your boot priorities are screwed up, in which case, just Option boot into OS X and from Terminal type (you'll need your root password, which by default should be your admin password):

sudo bless --mount / --setBoot