I added an HFile for C to the CodeBeautifier plugin, and I want to see how it turns out. Click ‘continue reading’ to see the actual code.
alarmClock is a program I wrote last semester for my Systems Programming course. The program is actually two programs; one that is a menu, and the other that is a timer. Signals are sent between the two processes to coordinate the alarm going off, hitting snooze, and quitting the program all together. Here is a sample with the timer set to five seconds, the snooze set at three seconds, and the ring “tone” set to ‘ringing’.
[augie@gohan alarmClock]$ ./alarmClock -t 5 -s 3 ringing wait_for_child
start
ringing
ringing
snooze
ringing
ringing
quiting
wait_for_child
wait_for_child
wait_for_child
wait_for_child
wait_for_child
child exited with code: 8
/*
* Name: August Schwer
* Date: 25 November 2003
* File: parseCommandLine.h
* Class: CS 451
* Purpose: Parse the command line arguments.
*/
#ifndef PARSE_COMMAND_LINE_H
#define PARSE_COMMAND_LINE_H
#include "argInfo.h"
/* parse command line args */
void parseCommandLine(int argc, char* argv[], argInfo* arg_info);
#endif /* PARSE_COMMAND_LINE_H */
/*
* Name: August Schwer
* Date: 01 December 2003
* File: parseCommandLine.c
* Class: CS 451
* Purpose: Parse the command line arguments.
*/
#include "parseCommandLine.h"
#include
#include
#include
/* parse command line args */
void parseCommandLine(int argc, char* argv[], argInfo* arg_info)
{
int i, got_ring_tone;
got_ring_tone = 0;
/* defaults */
strcpy(arg_info->time_seconds, "12");
strcpy(arg_info->snooze_seconds, "7");
strcpy(arg_info->ring_tone, "ring");
strcpy(arg_info->wait_tone, "waiting");
for(i=1; i < argc; ++i)
{
if( strcmp(argv[i],"-t") == 0 )
{
++i;
strcpy(arg_info->time_seconds, argv[i]);
}
else if( strcmp(argv[i], "-s") == 0 )
{
++i;
strcpy(arg_info->snooze_seconds, argv[i]);
}
else if(got_ring_tone == 0)
{
strcpy(arg_info->ring_tone, argv[i]);
got_ring_tone = 1;
}
else
{
strcpy(arg_info->wait_tone, argv[i]);
}
}
}
/*
* Name: August Schwer
* Date: 01 December 2003
* File: argInfo.h
* Class: CS 451
* Purpose: Container for argument info.
*/
#ifndef ARG_INFO_H
#define ARG_INFO_H
typedef struct
{
char time_seconds[10];
char snooze_seconds[10];
char ring_tone[50];
char wait_tone[50];
} argInfo;
#endif /* ARG_INF0_H */
/*
* kbhit.h
* Reads single characters from the keyboard.
*
* For cs 310, lab 2
* Robert G. Plantz -- 5 May 00
* Adapted from .....
*/
#ifndef KBHIT_H
#define KBHIT_H
void init_keyboard();
/*
* Sets up the keyboard for single character entry. Places it in
* non-canonical mode, turns off echo, and gets one character. The
* previous settings are saved.
*/
void close_keyboard();
/*
* Restores keyboard to previous (saved) state.
*/
int kbhit();
/*
* Returns 1 if key has been pushed, 0 if not.
*/
int readch();
/*
* If key has been pushed, returns the character. If not,
* waits until user pushes a key, then returns the character.
*/
#endif
/*
* kbhit.c
* Reads single characters from the keyboard.
*
* Four functions:
* void init_keyboard();
* Sets up the keyboard for single character entry
* void close_keyboard();
* Restores keyboard to original state
* int kbhit();
* Tells whether key has been struck or not
* int readch();
* Get the character is key has been struck
* For cs 310, lab 2
* Robert G. Plantz -- 5 May 00
*/
#include
#include
#include
#include
#include
#include "kbhit.h"
static struct termios initial_settings, new_settings;
static int peek_character = -1;
void init_keyboard()
{
tcgetattr(0,&initial_settings); /* save current settings */
new_settings = initial_settings; /* word from current settings */
new_settings.c_lflag &= ~ICANON; /* non-canonical mode */
new_settings.c_lflag &= ~ECHO; /* turn off echo */
new_settings.c_lflag &= ~ISIG; /* turn off keyboard signals */
new_settings.c_cc[VMIN] = 1; /* wait for one character */
new_settings.c_cc[VTIME] = 0; /* no timeout when waiting */
tcsetattr(0, TCSANOW, &new_settings); /* set the new settings */
}
void close_keyboard()
{
tcsetattr(0, TCSANOW, &initial_settings); /* restore old settings */
}
int kbhit()
{
char ch;
int nread;
if(peek_character != -1) /* a character has been read */
return 1;
new_settings.c_cc[VMIN] = 0; /* don't wait for a character */
tcsetattr(0, TCSANOW, &new_settings); /* but if a key has been */
nread = read(0, &ch, 1); /* pushed, get the character */
new_settings.c_cc[VMIN] = 1; /* back to the one character */
tcsetattr(0, TCSANOW, &new_settings); /* wait mode */
if(nread == 1) { /* if our peek got a */
peek_character = ch; /* character, store it */
return 1; /* and return true. */
}
return 0; /* else return false */
}
int readch()
{
char ch;
if(peek_character != -1) { /* if a previous peek gave us */
ch = peek_character; /* a character, get it */
peek_character = -1; /* and "erase" from storage */
return ch; /* give it to caller. */
}
read(0, &ch, 1); /* no character there from */
return ch; /* a previous peek, so wait */
}
/*
* Name: August Schwer
* Date: 02 December 2003
* File: timer.c
* Class: CS 451
* Purpose: alarm clock program.
*/
#include
#include
#include
#include
#include
#include
static int waiting, got_USR1, got_USR2, got_USR1_again;
static void alarm_handler(int, siginfo_t *, void *);
static void idle_handler(int, siginfo_t *, void *);
static void _alarm(sigset_t*, sigset_t*, sigset_t*, struct itimerval*);
static void _snooze(sigset_t*, sigset_t*, sigset_t*, struct itimerval*);
static void _quit(sigset_t*, sigset_t*, sigset_t*, struct itimerval*);
int main(int argc, char* argv[])
{
int alarm_sec, snooze_sec, wait_sec;
struct itimerval alarm_time;
struct itimerval snooze_time;
struct itimerval wait_time;
struct sigaction sig_action;
sigset_t block_mask, old_mask, zero_mask, idle_mask;
/* get command line arguments */
if(argc == 1)
{ perror("ERROR: timer called without any arguments."); exit(1); }
else if(argc < 4)
{ perror("ERROR: timer called with too few arguments."); exit(1); }
else if(argc > 4)
{ perror("ERROR: timer called with too many arguments."); exit(1); }
else
{
alarm_sec = strtol(argv[1],NULL,10);
snooze_sec = strtol(argv[2],NULL,10);
wait_sec = strtol(argv[3],NULL,10);
}
waiting = 1;
got_USR1 = 0;
got_USR2 = 0;
got_USR1_again = 0;
/* set up the timer values */
alarm_time.it_interval.tv_sec = 0;
alarm_time.it_interval.tv_usec = 0;
alarm_time.it_value.tv_sec = alarm_sec;
alarm_time.it_value.tv_usec = 0;
snooze_time.it_interval.tv_sec = 0;
snooze_time.it_interval.tv_usec = 0;
snooze_time.it_value.tv_sec = snooze_sec;
snooze_time.it_value.tv_usec = 0;
wait_time.it_interval.tv_sec = 0;
wait_time.it_interval.tv_usec = 0;
wait_time.it_value.tv_sec = wait_sec;
wait_time.it_value.tv_usec = 0;
/* set up signal action */
sig_action.sa_sigaction = alarm_handler;
sig_action.sa_flags = SA_SIGINFO;
sigemptyset(&sig_action.sa_mask);
sigaction(SIGALRM, &sig_action, NULL);
sig_action.sa_sigaction = idle_handler;
sigaction(SIGUSR1, &sig_action, NULL);
sigaction(SIGUSR2, &sig_action, NULL);
/* set up signal masks */
sigemptyset(&zero_mask);
sigemptyset(&block_mask);
sigemptyset(&idle_mask);
sigaddset(&block_mask, SIGALRM);
sigaddset(&idle_mask, SIGUSR1);
sigaddset(&idle_mask, SIGUSR2);
/* begin loop */
for(;;)
{
/* wait to receive the start signal */
/* block SIGUSR1 and SIGUSR2 */
sigprocmask(SIG_BLOCK, &idle_mask, &old_mask);
/* idle until signaled */
while(waiting)
{ sigsuspend(&zero_mask); }
/* reset signal mask */
sigprocmask(SIG_SETMASK, &old_mask, NULL);
waiting = 1;
/* the signal received determines what action to take */
if( (got_USR1 == 1) && (got_USR1_again == 0) )
{ /*printf("alarm\n");*/
/* ALARM */
_alarm(&block_mask, &old_mask, &zero_mask, &alarm_time);
}
else if(got_USR2 == 1)
{ /*printf("quit\n");*/
/* QUIT */
_quit(&block_mask, &old_mask, &zero_mask, &wait_time);
}
else
{ /*printf("snooze\n");*/
/* SNOOZE */
_snooze(&block_mask, &old_mask, &zero_mask, &snooze_time);
}
got_USR1_again = 0;
}/* end loop */
return 0;
}
static void alarm_handler(int a, siginfo_t *b, void *c)
{
waiting = 0;
}
static void idle_handler(int a, siginfo_t* info, void *c)
{
if(info->si_signo == SIGUSR1)
{
if(got_USR1 == 1)
{ got_USR1_again = 1; }
else
{ got_USR1 = 1; }
}
else if(info->si_signo == SIGUSR2)
{ got_USR2 = 1; got_USR1_again = 1; }
waiting = 0;
}
static void _alarm(sigset_t* block, sigset_t* old, sigset_t* zero, struct itimerval* alarm)
{
pid_t parent_pid;
parent_pid = getppid();
/* block SIGALRM */
sigprocmask(SIG_BLOCK, block, old);
/* set the alarm timer */
setitimer(ITIMER_REAL, alarm, 0);
/* wait for the timer to go off */
while(waiting)
{ sigsuspend(zero); }
/* reset signal mask */
sigprocmask(SIG_SETMASK, old, NULL);
waiting = 1;
/* signal parent */
kill(parent_pid, SIGUSR1);
}
static void _snooze(sigset_t* block, sigset_t* old, sigset_t* zero, struct itimerval* snooze)
{
pid_t parent_pid;
parent_pid = getppid();
/* block SIGALRM */
sigprocmask(SIG_BLOCK, block, old);
/* set the snooze timer */
setitimer(ITIMER_REAL, snooze, 0);
/* wait for the timer to go off */
while(waiting)
{ sigsuspend(zero); }
/* reset signal mask */
sigprocmask(SIG_SETMASK, old, NULL);
waiting = 1;
/* signal parent */
kill(parent_pid, SIGUSR1);
}
static void _quit(sigset_t* block, sigset_t* old, sigset_t* zero, struct itimerval* wait)
{
/* block SIGALRM */
sigprocmask(SIG_BLOCK, block, old);
/* set the wait timer */
setitimer(ITIMER_REAL, wait, 0);
/* wait for the timer to go off */
while(waiting)
{ sigsuspend(zero); }
/* reset signal mask */
sigprocmask(SIG_SETMASK, old, NULL);
exit(8);
}
/*
* Name: August Schwer
* Date: 02 December 2003
* File: main.c
* Class: CS 451
* Purpose: alarm clock program.
*/
#include "parseCommandLine.h"
#include "argInfo.h"
#include
#include
#include
#include "kbhit.h"
#include
#include
#include
#include
static int waiting, wait_child;
static void alarm_handler(int, siginfo_t *, void *);
static void child_handler(int, siginfo_t *, void *);
int main(int argc, char* argv[])
{
argInfo arg_info;
struct sigaction sig_action;
sigset_t block_mask, old_mask, zero_mask, child_mask;
int theChar, status;
pid_t pid;
waiting = 1;
wait_child = 1;
/* parse command line arguments */
parseCommandLine(argc, argv, &arg_info);
/* create child proccess */
if( (pid = fork()) < 0 )
{
perror("fork error\n");
exit(1);
}
else if(pid == 0) /* child process */
{
execlp("./timer","timer", arg_info.time_seconds, arg_info.snooze_seconds, "5", (char *) 0);
}
else /* parent */
{
/* set up signal action */
sig_action.sa_sigaction = alarm_handler;
sig_action.sa_flags = SA_SIGINFO;
sigemptyset(&sig_action.sa_mask);
sigaction(SIGUSR1, &sig_action, NULL);
sig_action.sa_sigaction = child_handler;
sigaction(SIGCHLD, &sig_action, NULL);
/* set up signal masks */
sigemptyset(&zero_mask);
sigemptyset(&block_mask);
sigemptyset(&child_mask);
sigaddset(&block_mask, SIGUSR1);
sigaddset(&child_mask, SIGCHLD);
init_keyboard();
for(;;)
{
if( kbhit() )
{
theChar = readch();
if(theChar == 's')
{ printf("start\n");
/* signal child to start alarm */
kill(pid, SIGUSR1);
/* block SIGUSR1 */
sigprocmask(SIG_BLOCK, &block_mask, &old_mask);
/* wait to receive signal back before going on */
while(waiting)
{ sigsuspend(&zero_mask); }
/* reset signal mask */
sigprocmask(SIG_SETMASK, &old_mask, NULL);
waiting = 1;
}
else if(theChar == 'z')
{ printf("snooze\n");
/* signal child to snooze */
kill(pid, SIGUSR1);
/* block SIGUSR1 */
sigprocmask(SIG_BLOCK, &block_mask, &old_mask);
/* wait to receive signal back before going on */
while(waiting)
{ sigsuspend(&zero_mask); }
/* reset signal mask */
sigprocmask(SIG_SETMASK, &old_mask, NULL);
waiting = 1;
theChar = 's';
}
else if(theChar == 'q')
{ printf("quiting\n");
/* signal child to quit */
kill(pid, SIGUSR2);
/* wait for child to exit */
while(wait_child)
{
printf("%s\n", arg_info.wait_tone);
sleep(1);
}
wait(&status);
if(WIFEXITED(status))
{
printf("child exited with code: %d\n", WEXITSTATUS(status));
}
else
{
printf("child exited abnormally.\n");
}
/* print waiting message */
close_keyboard();
return 0;
}
}
else if(theChar == 's')
{
/* print ring message */
printf("%s\n", arg_info.ring_tone);
sleep(1);
}
}
}
return 0;
}
static void alarm_handler(int a, siginfo_t *b, void *c)
{ waiting = 0; }
static void child_handler(int a, siginfo_t *b, void *c)
{ wait_child = 0; }