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

Reply via email to