hi,
ive written a small c wrapper for the crontab.
perhaps others can use this too, it follows the style of ewl.
a first beta with test is attached.
write does not work at the moment.
--
GruÃ,
Christian Holzberger
<[EMAIL PROTECTED]>
/* Providing EFL Style access to users crontab
* perhaps rename to eshed? because this can also be used on windows with some tweaking
* i guess you have to set CRONTAB_LIST to other value than crontab -l
*
* why i use popen instead of fopen the ~/.contab
* 1: the crontab has to be registered to the system
* 2: popen makes it possible to do this on systems not compatible with unix style crontabs
*/
#include "ecron.h"
#define CRONTAB_LIST "crontab -l"
#define CRONTAB_SAVE "crontab -"
#define CRONTAB_MAX_LENGTH 256
#define DEBUG
#define strtrim _ECRON__strtrim
char* _ECRON__strtrim (char *str) {
int i,str_length=0;
unsigned int found=0;
for (i=0;i < strlen (str) ;i++) {
if ((!found && str[i] == ' ' ) || str [i]=='\n') continue;
found=1;
str[str_length++]=str[i];
}
str[str_length] = '\0';
return str;
}
#define mstrcpy _ECRON__mstrcpy
char* _ECRON__mstrcpy (char *tocopy) {
char *x;
x = malloc (strlen (tocopy) * sizeof (char));
strcpy (x,tocopy);
return x;
}
#define write_env _ECRON__write_env
void _ECRON__write_env (char* id, char* value,FILE* proc) {
/* if value != NULL */
if ( value == NULL ) return;
fputs (id,proc);
fputs ("=",proc);
fputs (value,proc);
fputs ("\n",proc);
}
ecron_crontab* ecron_crontab_open () {
FILE* proc; /* used to open the crontab -l command as file */
char *str; /* temp store crontab string */
ecron_crontab* crontab=NULL; /* the crontab with all needed info */
ecron_task* task=NULL; /* all tasks in the opend crontab */
int i,memsize=0;
char *writeto=NULL;
unsigned int command=0;
str = malloc ( sizeof (char) * CRONTAB_MAX_LENGTH); /* allocate string */
proc = popen (CRONTAB_LIST,"r" ); /* get output of crontab -l */
crontab = malloc ( sizeof (ecron_crontab) );
crontab->tasks = NULL;
crontab->tasks_length = 0;
crontab->env_home = NULL;
crontab->env_mailto = NULL;
crontab->env_shell = NULL;
// task->special = malloc ( sizeof (char));
while ( NULL != fgets (str, CRONTAB_MAX_LENGTH, proc) ) {
task = malloc ( sizeof (ecron_task) );
/* parse contents of crontab entrys, validate the input */
/* posibility 1: minute .... command */
task->special = NULL;
task->command = NULL;
task->minute = NULL;
task->hour = NULL;
task->day_of_month = NULL;
task->month = NULL;
task->day_of_week = NULL;
strtrim (str); /* strip all leading whitespaces and remove \n */
/* parse content of USER MAILTO and SHELL variables, if not set find out the current user, ignore mail and shell */
if ( crontab->env_mailto == NULL && strstr ( str, "MAILTO") ) {
for ( i=0; i < strlen ( str );i++) {
if ( writeto != NULL ) {
writeto = (char*)realloc ( writeto,sizeof (char) * (memsize+2) );
writeto[memsize]=str[i];
writeto[++memsize]='\0';
}
if ( str[i] == '=' && writeto == NULL) { /* after first = sign */
writeto = (char*)realloc ( writeto,sizeof (char) );
memsize=0;
} else if (i+1 == strlen (str) ) {
crontab->env_mailto = strtrim(writeto);
writeto=NULL;
memsize=0;
}
}
free(task);
task=NULL;
#ifdef DEBUG
printf ("ecron_crontab_open(): maito: %s\n", crontab->env_mailto);
#endif
} else if ( crontab->env_home == NULL && strstr ( str, "HOME") ) {
for ( i=0; i < strlen ( str );i++) {
if ( writeto != NULL ) {
writeto = (char*)realloc ( writeto,sizeof (char) * (memsize+2) );
writeto[memsize]=str[i];
writeto[++memsize]='\0';
}
if ( str[i] == '=' && writeto == NULL) { /* after first = sign */
writeto = (char*)realloc ( writeto,sizeof (char) );
memsize=0;
} else if (i+1 == strlen (str) ) {
crontab->env_home = strtrim(writeto);
writeto=NULL;
memsize=0;
}
}
free(task);
task=NULL;
#ifdef DEBUG
printf ("ecron_crontab_open(): home: %s\n", crontab->env_home);
#endif
} else if ( crontab->env_shell == NULL && strstr ( str, "SHELL") ) {
for ( i=0; i < strlen ( str );i++) {
if ( writeto != NULL ) {
writeto = (char*)realloc ( writeto,sizeof (char) * (memsize+2) );
writeto[memsize]=str[i];
writeto[++memsize]='\0';
}
if ( str[i] == '=' && writeto == NULL) { /* after first = sign */
writeto = (char*)realloc ( writeto,sizeof (char) );
memsize=0;
} else if (i+1 == strlen (str) ) {
crontab->env_shell = strtrim (writeto);
writeto=NULL;
memsize=0;
}
}
#ifdef DEBUG
printf ("ecron_crontab_open(): shell: %s\n", crontab->env_shell);
#endif
free(task);
task=NULL;
} else if ( str [0] == '@' ) { /* got an @command */
for ( i=0; i < strlen ( str );i++) {
writeto = (char*)realloc ( writeto,sizeof (char) * (memsize+2) );
writeto[memsize]=str[i];
writeto[++memsize]='\0';
if ( task->special == NULL && str[i] == ' ' ) { /* on FIRST whitespace */
task->special=writeto;
writeto=NULL;
memsize=0;
} else if (i+1 == strlen (str) ) {
task->command = writeto;
writeto=NULL;
memsize=0;
}
}
#ifdef DEBUG
printf ("ecron_crontab_open():@command [0]=%c *=%s\nspecial: %s command: %s\n", str[0],str,task->special,task->command);
#endif
} else if ( str[0] >= '0' && str[0] <='9' ) { /* see if first value is between '0' and '9' */
for ( i=0; i < strlen ( str );i++) {
writeto = (char*)reallocf ( writeto,sizeof (char) * (memsize+2) );
writeto[memsize]=str[i];
writeto[++memsize]='\0';
if ( task->minute == NULL && str[i] == ' ' ) { /* on FIRST whitespace */
task->minute=writeto;
writeto=NULL;
memsize=0;
} else if ( task->hour == NULL && str[i] == ' ' ) {
task->hour = writeto;
writeto=NULL;
memsize=0;
} else if ( task->day_of_month == NULL && str[i] == ' ' ) {
task->day_of_month = writeto;
writeto=NULL;
memsize=0;
} else if ( task->month == NULL && str[i] == ' ' ) {
task->month = writeto;
writeto=NULL;
memsize=0;
} else if ( task->day_of_week == NULL && str[i] == ' ' ) {
task->day_of_week = writeto;
writeto=NULL;
memsize=0;
} else if ( i+1 == strlen (str) ) {
task->command = strtrim(writeto);
writeto=NULL;
memsize=0;
}
}
#ifdef DEBUG
printf ("ecron_crontab_open():hour: %s day_of_month: %s command:%s\n", task->hour,task->day_of_month, task->command);
#endif
} else { /* comment or unhandled */
free(task);
task=NULL;
}
/* add the ecron_task!!!!*/
if (task != NULL)
ecron_crontab_struct_task_add ( crontab, task );
}
/* close proc */
free (str);
pclose (proc);
return crontab;
}
void ecron_crontab_write (ecron_crontab* ec) {
/* call popen to write crontab */
FILE* proc; /* used to open the crontab -l command as file */
proc = popen (CRONTAB_SAVE,"w" );
/* write env vars */
write_env ("HOME", ec->env_home,proc);
write_env ("SHELL", ec->env_shell,proc);
write_env ("MAILTO", ec->env_mailto,proc);
pclose (proc);
}
void ecron_crontab_write_close (ecron_crontab* ec) {
/* write the crontab */
ecron_crontab_write (ec);
/* free all pointers */
ecron_crontab_close(ec);
}
void ecron_crontab_close (ecron_crontab* ec) {
ecron_task** tasks;
int i;
/* free the strings and ecron_* data structs */
free (ec->env_mailto);
free (ec->env_home);
free (ec->env_shell);
tasks = ecron_crontab_task_list_get(ec);
for ( i=0; i< ecron_crontab_task_list_length_get (ec);i++) {
free (tasks[i]->command);
free (tasks[i]->day_of_month);
free (tasks[i]->day_of_week);
free (tasks[i]->hour);
free (tasks[i]->minute);
free (tasks[i]->month);
free (tasks[i]->special);
free (tasks[i]);
}
free (tasks);
free (ec);
}
ecron_task** ecron_crontab_task_list_get (ecron_crontab* ec) {
return ec->tasks;
}
int ecron_crontab_task_list_length_get (ecron_crontab* ec) {
return ec->tasks_length;
}
void ecron_crontab_struct_task_add (ecron_crontab* ec,ecron_task* t) {
/* realloc ecron_crontab->tasks */
ec->tasks_length++;
ec->tasks = (ecron_task**)realloc ( ec->tasks, ec->tasks_length * sizeof (ecron_task**) );
/* append the task */
ec->tasks[ec->tasks_length-1] = t;
#ifdef DEBUG
printf ("ecron_crontab_struct_task_add():hour: %s day_of_month: %s command:%s\n", ec->tasks[ec->tasks_length-1]->hour,ec->tasks[ec->tasks_length-1]->day_of_month, ec->tasks[ec->tasks_length-1]->command);
#endif
}
void ecron_crontab_task_add (ecron_crontab* ec, char* minute, char* hour, char* day_of_month, char* month, char* day_of_week, char* command) {
// FIXME malloc & strcpy
/* construct ecron_task */
ecron_task *task;
task=malloc (sizeof (ecron_task));
task->minute = mstrcpy (minute);
task->day_of_month= mstrcpy(day_of_month);
task->day_of_week= mstrcpy(day_of_week);
task->hour= mstrcpy (hour);
task->minute= mstrcpy (minute);
task->month= mstrcpy(month);
task->special=NULL;
task->command=mstrcpy (command);
/* append the task */
ecron_crontab_struct_task_add(ec,task);
}
void ecron_crontab_special_task_add ( ecron_crontab* ec, char *special , char *command) {
// FIXME malloc & strcpy
/* construct ecron_task */
ecron_task *task;
task=malloc (sizeof (ecron_task));
task->minute = NULL;
task->day_of_month=NULL;
task->day_of_week= NULL;
task->hour=NULL;
task->minute=NULL;
task->month=NULL;
task->special = mstrcpy (special);
task->command = mstrcpy (command);
/* append the task */
ecron_crontab_struct_task_add(ec,task);
}
void ecron_crontab_task_del (ecron_crontab* ec,ecron_task* t) {
ecron_task** tasks;
int i;
tasks = ecron_crontab_task_list_get(ec);
for ( i=0; i< ecron_crontab_task_list_length_get (ec);i++) {
if ( tasks [i] == t ) {
free (tasks [i]);
tasks[i]=NULL;
return;
}
}
}
void ecron_crontab_shell_set (ecron_crontab* ec,const char* sh) {
free (ec->env_shell);
ec->env_shell = malloc (strlen (sh) * sizeof (char));
strcpy (ec->env_shell,sh);
}
void ecron_crontab_home_set (ecron_crontab* ec,const char *hm) {
free (ec->env_home);
ec->env_home = malloc (strlen (hm) * sizeof (char));
strcpy (ec->env_home,hm);
}
void ecron_crontab_mailto_set (ecron_crontab* ec,const char *hm) {
free (ec->env_mailto);
ec->env_mailto = malloc (strlen (hm) * sizeof (char));
strcpy (ec->env_mailto,hm);
}
/* Questions:
* how to handle crontab resume if the pc was powered of while an task should be ran
* -> see anacron
* what about the at commando
*/
#ifndef _ECRON_H_
#define _ECRON_H_
#include <stdio.h>
/** discribing an task in the crontab */
struct ecron_task_t {
char* special;
char* minute;
char* hour;
char* day_of_month;
char* month;
char* day_of_week;
char* command;
} typedef ecron_task;
/** discribing the open crontab */
struct ecron_crontab_t {
/* Environment variables */
char* env_shell;
char* env_mailto;
char* env_home;
char *user;
unsigned int open;
int tasks_length;
ecron_task** tasks;
} typedef ecron_crontab;
/** open / parses the crontab */
ecron_crontab* ecron_crontab_open ();
/** writes the crontab of current user*/
void ecron_crontab_write(ecron_crontab* ec);
/** frees all pointers used for parsing and providing functionality to the user */
void ecron_crontab_close(ecron_crontab* ec);
/** see ecron_crontab_write() and ecron_crontab_close() */
void ecron_crontab_write_close(ecron_crontab* ec);
/** adds a new Task to the end of the crontab ec, NULL is converted to "*"
* see man crontab
* FIXME: limitations on specifing rages the "man 6 crontab"
* and how is this handeld on windows, may one specifiy ranges?
*/
void ecron_crontab_task_add (ecron_crontab* ec, char* minute, char* hour, char* day_of_month, char* month, char* day_of_week, char* command);
/** adds task to the end of the actual crontab
* the space pointed by task is freed by ecron_crontab_close() */
void ecron_crontab_struct_task_add (ecron_crontab* ec, ecron_task* task);
/** Adds a task at a special time. special may be one of:
* @reboot
* @yearly or @annually (
* @monthly
* @weekly
* @daily
* @midnight
* @hourly
* FIXME: i think this only works on FreeBSD systems, but iam not shure?! perhaps we should add our own
* @ commands and parse them to an normal task
* */
void ecron_crontab_special_task_add ( ecron_crontab* ec, char *special , char *command);
/** gets a list of crontab entrys for the current user
* last entry is NULL
* */
ecron_task** ecron_crontab_task_list_get (ecron_crontab* ec);
/** returns the length of the crontab tasks list */
int ecron_crontab_task_list_length_get (ecron_crontab* ec);
/** deletes the task described by t */
void ecron_crontab_task_del (ecron_crontab* ec,ecron_task* t);
/** sets the crontab SHELL variable */
void ecron_crontab_shell_set (ecron_crontab* ec,const char* sh);
/** sets the crontab HOME variable */
void ecron_crontab_home_set (ecron_crontab* ec,const char *hm);
/** sets the crontab MAILTO variable */
void ecron_crontab_mailto_set (ecron_crontab* ec,const char *hm);
#endif //_ECRON_H_
#include "ecron.h"
int main ( int* n, char **args) {
ecron_crontab* mycron;
ecron_task** mytasks;
int i;
mycron = ecron_crontab_open();
ecron_crontab_mailto_set(mycron, "[EMAIL PROTECTED]");
ecron_crontab_special_task_add (mycron,"@reboot","echo reboot");
mytasks = ecron_crontab_task_list_get(mycron);
for ( i=0; i< ecron_crontab_task_list_length_get (mycron);i++) {
if (mytasks[i]->command != NULL)
printf ("TASK: %s\n",mytasks[i]->command);
}
//ecron_crontab_write (mycron);
ecron_crontab_close (mycron);
return 0;
}