LCC-win32: Drupal Cron

MPG UniCenter

MPG UniCenter

lcc-win32 C compiler.

LCC Drupal Cron (Portable Cron)

On the previous page I covered a simple delay program this page expands on that to produce a portable cron application targeted at Drupal. I covered how to use unidelay.exe to produce a generic cron application on this page it is worth reading for background information.

Top

Requirement

Our program will periodically run the following system command line:

udrive\usr\local\php\php.exe -n udrive\www\run_cron.php

It runs php.exe in CLI mode (switch -n prevents php.ini file being read), which in turn runs script run_cron.php located in the server web root folder www. This script contains a single line which runs Drupal’s cron.php script.

Top

Proposed solution

The above line can be hard-coded within a delay loop. Assumes a fixed time; a user will always install Drupal in the root folder www and location of the PHP executable will never change.

Restrictive

Hard coding makes the program very restrictive, suppose a user wishes to have a different delay or decides to install Drupal in a sub-folder named drupal or some other folder. The location of PHP executable is unlikely to change but is possible.

Flexibility

Remember we have the ability to pass parameters to our program making it much more flexible. If the above hard-coded variables are made defaults they can be overridden using parameters.

Order of parameters passed to our program is important, what will a user most likely want to change. I would go for delay followed by path to Drupal the least likely will be the path to PHP unless a user has redesigned Uniform Server. However including it as a parameter increases flexibility.

Top

Implementation

The command line to run our program looks similar to the following:

drupal_cron.exe delay path_to_drupal path_to_php

You will notice I have given the program and parameters a name these can be used later within the program as variables.

I will place one restriction; our program shall be located in folder “Uniform Server” or any folder above both php and drupal folders. This means the paths are relative to the location of our program. Makes it both easier to program and for a user to correctly name the paths.

Top

Code flow

This should be a flow diagram however a few words can express the intended idea and logic. It can be a pain, keep it short.

  • Start
  • Set defaults
  • If no delay parameter use default
  • If no path_to_drupal parameter use default
  • If no path_to_php parameter use default
  • Start loop
  • Delay
  • Run system command path_to_php\php.exe -n path_to_drupal\run_cron.php
  • Go to Start loop
  • End

Top

Coding

From the above you can start coding. I tend to add loads of comments in the hope when re-read in the future I will understand it. Its all a mater of personal style the following is one coding solution:

#include <stdheaders.h>
#include <windows.h>
#include <io.h>

int main(int argc,char *argv[])
{
  //== Variables
  int delay;                    // Delay required
  char path_to_drupal[80]="";   // relative pat to Drupal
  char path_to_php[80]="";      // relative path to php
  char error_message[200]="";   // error message string
  char cmd_string[200]="";      // command line string

  //== Default values
  int default_delay=600000;     // 1000ms gives 1s delay
                                // 600000 = 10 mins
  char default_path_to_drupal[80]="udrive\\www\\run_cron.php";
  char default_path_to_php[80]="udrive\\usr\\local\\php\\php.exe";

  //== Set variables according to parameter supplied ===================
  if(argc==1){                                      // No parameters
    delay = default_delay;                          // hence use defaults
    strcat(path_to_drupal, default_path_to_drupal);
    strcat(path_to_php, default_path_to_php);
  }

  if(argc==2){
    delay = default_delay * (int)atoi(argv[1]);     // New delay required
    strcat(path_to_drupal, default_path_to_drupal); // All other use
    strcat(path_to_php, default_path_to_php);       // defaults
  }

  if(argc==3){
    delay = default_delay * (int)atoi(argv[1]);     // New delay required
    strcat(path_to_drupal, argv[2]);                // New drupal path
    strcat(path_to_php, default_path_to_php);       // Use default
  }

  if(argc==4){
    delay = default_delay * (int)atoi(argv[1]);     // New delay required
    strcat(path_to_drupal, argv[2]);                // New drupal path
    strcat(path_to_php, argv[3]);                   // New php path
  }
  //== End set vars =====================================================

  //== Check if files exists ============================================
  if( _access(path_to_drupal,0) !=0 ) // File not found alert user
  {
	strcat(error_message, path_to_drupal);
	strcat(error_message, "\n\n File not found\n\n No action taken");
	MessageBox (NULL, error_message , "Path to Drupal", 0);
	return 1;                         // Give up its not going to work
  }

  if( _access(path_to_php,0) !=0 )    // File not found alert user
  {
	strcat(error_message, path_to_php);
	strcat(error_message, "\n\n File not found\n\n Noaction taken");
	MessageBox (NULL, error_message , "Path to PHP", 0);
	return 1;                        // Give up its not going to work
  }

 //== End Check if files exists ============================================

 //== Build command string ==============================
 strcat(cmd_string, path_to_php);
 strcat(cmd_string, " -n ");         // Prevents ini read
 strcat(cmd_string, path_to_drupal);
 //== End Build command string ==========================

 //== Infinite loop, run process hidden =====================
 while (1){                       //loop forever
   _System(cmd_string, SW_HIDE);  // Run hidden child process
   sleep(delay);                  // Delay for specified time
 }
//== End Infinite loop, run process hidden ===================

  return 0; // Exit! Will never reach this point beause
            // process exrernally killed.
}

Note: If you are looking for particular functions check out LCC standard library. Click Help link (top right ) from the drop down menu you will find various help files including the standard library.

The code is self-explanatory however there are a few things worthy of note.

Top

File existence

It is possible to create your own function to check the existence of a file the code would look similar to this:

bool file_exists(const char * filename)
{
    FILE *fp;
    if (fp = fopen(filename, "r"))
    {
        fclose(fp);
        return true;
    }
    return false;
}

This may in certain situations produce unreliable results hence its far better to use a function specifically designed for this task hence the reason for using this function:

_access(path_to_drupal,0)

It returns "0" if the file exists otherwise it returns "-1"

Top

Command Window

If you use the standard system command to run php.exe

system(cmd_string)

a command window opens until the program executions ends. Although relatively fast it produces an annoying black screen flash.

Ideally the program should be run in a hidden window hence the use of this function:

_System(cmd_string, SW_HIDE)

Top

Creating a new LCC project

On the previous page I used different names for the project folder and executable it makes it slightly easier to create a new project if the names are identical. I will be creating the following project drupal_cron

Top

Create Project

  1. Start LCC
  2. Close any open projects: Project > Close click Yes to confirm
  3. Create project: Project > Create opens Definition of new project window
    1. Name of the new project: Enter drupal_cron
    2. Sources: Click Browse navigate to E:\lcc\projects click OK add \drupal_cron to give E:\lcc\projects\drupal_cron
    3. Output directory: Click in this window automatically updates to give E:\lcc\projects\drupal_cron\lcc
    4. Type of project: Radio button defaults to Console Application leave selected
    5. Click Create (button top right)
  4. Do you want to use the wizard to generate the application skeleton: Click Yes
  5. Application characteristics displayed: Click OK click OK to Lcc wizard pop-up
  6. Compiler settings displayed: Click Next
  7. Linker settings displayed: Click Next
  8. Debugger settings displayed: Click Finish

Project page drupal_cron.c will be displayed

Top

Edit Code

  1. Delete everything in drupal_cron.c
  2. Copy the above code into drupal_cron.c
  3. File > Save

Top

Test for errors

  1. Compiler > Make There should be no errors
  2. Compiler > Execute drupal_cron.exe Path to Drupal pop file not found - Indicates its working
  3. Create the following folder chain: E:\lcc\projects\drupal_cron\lcc\udrive\www
  4. In folder www create a blank file named run_cron.php
  5. Compiler > Execute drupal_cron.exe Path to PHP pop file not found - Indicates its working

Note: You can create a similar path to php and use a dummy file. The program is working lets create the final code.

Top

Configuration

  1. Project > Configuration opens configuration window.
  2. Click Compiler tab and set the following:
    1. Check Optimise
    2. Check Eliminate unused assignments
    3. UnCheck Generate debug info
  3. Click Linker tab and set the following:
    1. Type of output: Click in Windows appl radio button
    2. Click OK Allow to rebuild OK, Ignore any errors click OK

Top

Compile

  1. Compiler > Make
  2. Compiler > Compile drupal_cron.c
  3. Pick-up the finished program drupal_cron.exe in E:\lcc\projects\drupal_cron\lcc
  4. Copy this file to "Uniform Server"

Top

Other files

To recap I have assumed Drupal has been installed in the root folder www.

Uniform Server

The folder "Uuiform Server" contains the following files:

  • drupal_cron.exe

You can directly run this file if you have set the defaults to meet your requirements.

  • drupal_cron.bat

Alternatively you can start drupal_cron.exe using a batch file and pass parameters to it. For example create drupal_cron.bat and add this line:

start drupal_cron.exe 1 udrive\www\run_cron.php udrive\usr\local\php\php.exe

The above would have no effect since the parameters passed are the defaults.

If you want to change the delay to 1 hour and installed Drupal to sub-folder www\drupal the batch file now looks like this:

start drupal_cron.exe 6 udrive\www\drupal\run_cron.php 
  • stop_drupal_cron.bat

If you want to manually stop drupal_cron.exe without relaying on turning your PC off create a batch file named stop_drupal_cron.bat and add the following line:

udrive\home\admin\program\pskill.exe drupal_cron.exe c

Drupal root folder

Drupal's root folder (where file cron.php is located) must contain the following PHP script file. Create a new file run_cron.php and add the following line:

<? $dummy = file("http://localhost/cron.php"); ?>

Top

Alternative start and stop

An alternative to using separate batch files to start and stop drupal_cron.exe is to add the appriate line of code to the end of Uniform Server's start and stop files.

Note: At the bottom of each file you will see :END add the one liner below this.

Top

Summary

If you have never considered using Drupal now you have a good excuse to try it. You can install it on a separate Uniform Server fire it up and have a play. Add your new compiled script and check it works.

Real point of the above is to provide real working code that can be compiled with lcc. At first sight it looks difficult to use, this invariably is down to knowing where to start. I hope this page and the pervious ones have pointed you in the right direction. I have noticed over the years fancy programming language come and go but C remains there in a prominent position.

Top


  Ric