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; }