So I am trying to learn C and am coding some scripts on my own.
For a start I have decided to port the shell script developed by wisecracker into C.( Here is the link to that script A simple reminder script for beginners to shell scripting. | Unix Linux Forums | OS X (Apple) )
This is what I have done so far:
/************************************************************************
*Usage
*To start : ./reminder -k start -t "Text to remind" -c "repeat time"
*To stop : ./remnder -k stop
*/
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sysexits.h>
#include <string.h>
void usage(char * const *arg) {
printf ("Usage : %s [OPTIONS]\n",arg[0]);
printf (" -k start/stop\n");
printf (" -t <Reminder text>\n");
printf (" -c <countdown(30-300)>\n");
printf (" -h Help on usage. ");
printf ("\n");
exit(EX_USAGE);
}
void start_routine(char *myname, char *rem, int countdown) {
FILE *fd = NULL;
char *script;
strcpy(script,"./reminder.sh");
char *content = malloc(1000 * sizeof(char));
if ( !(fd = fopen(script,"w+")) ) {
printf("Unable to open/create %s\n",script);
printf("Error code is %d\n",fd);
exit(EX_CANTCREAT);
}
if (chmod(script,S_IXUSR|S_IRUSR|S_IWUSR|S_IXGRP)) {
printf("Unable to give execute permission to %s\n",script);
remove(script);
exit(EX_CANTCREAT);
}
sprintf(content,"#/bin/bash\n");
sprintf(content,"%sprintf \'\\033[2J\\033[H\'\n",content);
sprintf(content,"%sprintf '\\033[1m\\033[12;3f%s\\033[0m\\n\\n'\n",content,rem);
sprintf(content,"%ssleep 5\n",content);
sprintf(content,"%sexit 0\n",content);
fwrite(content,sizeof(char),strlen(content),fd);
fclose(fd);
free(content);
while (1) {
system("xterm -e ./reminder.sh &");
sleep(countdown);
}
}
void stop_routine() {
return;
}
int main(int argc,char * const *argv) {
char * myname = argv[0];
int opt;
int kflag = 0;
int tflag = 0;
int cflag = 0;
char *state;
char *text;
int countdown;
int start = 0;
int stop = 0;
pid_t parent_pid,child_pid,pid;
int status;
parent_pid=getpid();
while ((opt = getopt(argc, argv,"hk:t:c:")) != -1 ) {
switch (opt) {
case 'k' :
kflag = 1;
//DEBUG
//printf("optarg : %s\n",optarg);
state = optarg;
break;
case 't' :
tflag = 1;
text = optarg;
break;
case 'c' :
cflag = 1;
countdown = atoi(optarg);
break;
case 'h' :
usage (argv);
break;
/* case '?' :
printf("%s: invalid option.\n",argv[0]);
usage(argv);
break;
*/
}
}
//DEBUG
//printf("%s\n",state);
if (!kflag) {
printf ("%s: missing -k option.\n",myname);
usage(argv);
} else if (strcmp(state,"start") && strcmp(state,"stop")) {
printf ("%s: illegel use -k option.\n",myname);
usage(argv);
}
if (!tflag) {
strcpy(text,"Are you forgetting something?");
}
if (!cflag) {
countdown = 60;
} else if (countdown < 30 || countdown >300) {
countdown = 60;
}
//Check if the program was invoked to start or stop the applicatio.
if ( ! strcmp(state,"start")) // if (state == "start")
start = 1;
else
stop = 1;
printf ("\033[2J\033[H");
if ( start ) {
/* The reminder text and the countdown is printed in
* the main window.
* This will be done by a child process.
* We will fork() off now and let the child do the rest of the
* starting up. So to stop the program we will just kill of the child.
*/
printf("Starting %s with the below inputs\n",myname);
printf ("\nReminder text : %s\n",text);
printf ("Repeat time : %d\n\n",countdown);
printf ("Run %s with -k stop to stop\n",myname);
if (( child_pid = fork() ) == -1) {
perror("fork error");
exit(EX_UNAVAILABLE);
}
} else {
printf("Stopping %s\n",myname);
stop_routine();
exit(EX_OK);
}
if (! child_pid) { //Child process
start_routine(myname,text,countdown);
} else { //Parent process
if ((pid = wait(&status)) == -1) {
perror("Wait error\n");
exit(EX_UNAVAILABLE);
}
if (WEXITSTATUS(status)) {
printf("Reminder has finished exectution.\n");
return 0;
} else if (WIFSIGNALED(status)) {
if ( WTERMSIG(status) == 6 ) {
printf("Reminder stopped normally using -k stop option\n");
return 0;
} else {
printf("Reminder terminated abnormally by signale: %d\n",
WTERMSIG(status));
exit(EX_UNAVAILABLE);
}
}
}
return 0;
}
So here is the problems that I am facing now:
- How do I stop this? I mean how can I make
./reminder -k stop
to work? I thought about writing the pid of the parent to file and then using it to stop the program. - How can put the parent to background so that I get my stdin back at prompt? Now what happens is that the parent keeps waiting for the child to end, which never happens. What I did was I just removed the
wait(&status)
and replace it withreturn 0;
. So now the parent will exit and the child will keep on popping up the reminder texts.
Thanks.