==03/12/14==
Fitting, then, that my first update to my opus is monumental in length. The following are the exercises from chapter 7. These really escalated in complexity.
hello1.c
#include
#include
main()
{
initscr() ; /* turn on curses */
/* send requests */
clear(); /* clear screen */
move(10,20); /* row10,col20 */
addstr("Hello, world"); /* add a string */
move(LINES-1,0); /* move to LL */
refresh(); /* update the screen */
getch(); /* wait for user input */
endwin(); /* turn off curses */
}
hello2.c
#include
#include
main()
{
int i;
initscr(); /* turn on curses */
clear(); /* draw some stuff */
for(i=0; i
hello3.c
#include
#include
main()
{
int i;
initscr();
clear();
for(i=0; i
hello4.c
#include
#include
main()
{
int i;
initscr();
clear();
for(i=0; i
hello5.c
#include
#define LEFTEDGE 10
#define RIGHTEDGE 30
#define ROW 10
main()
{
char message[] = "Hello";
char blank[] = " ";
int dir = +1;
int pos = LEFTEDGE ;
initscr();
clear();
while(1){
move(ROW,pos);
addstr( message ); /* draw string */
move(LINES-1,COLS-1); /* park the cursor */
refresh(); /* show string */
sleep(1);
move(ROW,pos); /* erase string */
addstr( blank );
pos += dir; /* advance position */
if ( pos >= RIGHTEDGE ) /* check for bounce */
dir = -1;
if ( pos <= LEFTEDGE )
dir = +1;
}
}
Up until now, these 5 examples have been playing with the curses library, creating text and moving text.
sleep1.c - demonstrates sleep()
#include
#include
// #define SHHHH
main()
{
void wakeup(int);
printf("about to sleep for 4 seconds\n");
signal(SIGALRM, wakeup); /* catch it */
alarm(4); /* set clock */
pause(); /* freeze here */
printf("Morning so soon?\n"); /* back to work */
}
void wakeup(int signum)
{
#ifndef SHHHH
printf("Alarm received from kernel\n");
#endif
}
ticker_demo.c - demonstrates to the programmer how an interval timer can be used to generate regular signals
#include
#include
#include
int main()
{
void countdown(int);
signal(SIGALRM, countdown);
if ( set_ticker(500) == -1 )
perror("set_ticker");
else
while( 1 )
pause();
return 0;
}
void countdown(int signum)
{
static int num = 10;
printf("%d ..", num--);
fflush(stdout);
if ( num < 0 ){
printf("DONE!\n");
exit(0);
}
}
/* [from set_ticker.c]
* set_ticker( number_of_milliseconds )
* arranges for interval timer to issue SIGALRM's at regular intervals
* returns -1 on error, 0 for ok
* arg in milliseconds, converted into whole seconds and microseconds
* note: set_ticker(0) turns off ticker
*/
int set_ticker( int n_msecs )
{
struct itimerval new_timeset;
long n_sec, n_usecs;
n_sec = n_msecs / 1000 ; /* int part */
n_usecs = ( n_msecs % 1000 ) * 1000L ; /* remainder */
new_timeset.it_interval.tv_sec = n_sec; /* set reload */
new_timeset.it_interval.tv_usec = n_usecs; /* new ticker value */
new_timeset.it_value.tv_sec = n_sec ; /* store this */
new_timeset.it_value.tv_usec = n_usecs ; /* and this */
return setitimer(ITIMER_REAL, &new_timeset, NULL);
}
sigdemo3.c - We toyed around with this concept on Tuesday, using signal()
#include
#include
#define INPUTLEN 100
main(int ac, char *av[])
{
void inthandler(int);
void quithandler(int);
char input[INPUTLEN];
int nchars;
signal( SIGINT, inthandler ); /* set handler */
signal( SIGQUIT, quithandler ); /* set handler */
do {
printf("\nType a message\n");
nchars = read(0, input, (INPUTLEN-1));
if ( nchars == -1 )
perror("read returned an error");
else {
input[nchars] = '\0';
printf("You typed: %s", input);
}
}
while( strncmp( input , "quit" , 4 ) != 0 );
}
void inthandler(int s)
{
printf(" Received signal %d .. waiting\n", s );
sleep(2);
printf(" Leaving inthandler \n");
}
void quithandler(int s)
{
printf(" Received signal %d .. waiting\n", s );
sleep(3);
printf(" Leaving quithandler \n");
}
sigactdemo.c - goes beyond signal() and demonstrates how we may utilize sigaction() to intercept signals.
#include
#include
#define INPUTLEN 100
main()
{
struct sigaction newhandler; /* new settings */
sigset_t blocked; /* set of blocked sigs */
void inthandler(); /* the handler */
char x[INPUTLEN];
/* load these two members first */
newhandler.sa_handler = inthandler; /* handler function */
newhandler.sa_flags = SA_RESETHAND | SA_RESTART; /* options */
/* then build the list of blocked signals */
sigemptyset(&blocked); /* clear all bits */
sigaddset(&blocked, SIGQUIT); /* add SIGQUIT to list */
newhandler.sa_mask = blocked; /* store blockmask */
if ( sigaction(SIGINT, &newhandler, NULL) == -1 )
perror("sigaction");
else
while( 1 ){
fgets(x, INPUTLEN, stdin);
printf("input: %s", x);
}
}
void inthandler(int s)
{
printf("Called with signal %d\n", s);
sleep(s);
printf("done handling signal %d\n", s);
}
bounce1d.c - user controlled animation, as in user defined speed and direction! VIDJA GAMES
#include
#include
#include
/* some global settings main and the handler use */
#define MESSAGE "hello"
#define BLANK " "
int row; /* current row */
int col; /* current column */
int dir; /* where we are going */
int main()
{
int delay; /* bigger => slower */
int ndelay; /* new delay */
int c; /* user input */
void move_msg(int); /* handler for timer */
initscr();
crmode();
noecho();
clear();
row = 10; /* start here */
col = 0;
dir = 1; /* add 1 to row number */
delay = 200; /* 200ms = 0.2 seconds */
move(row,col); /* get into position */
addstr(MESSAGE); /* draw message */
signal(SIGALRM, move_msg );
set_ticker( delay );
while(1)
{
ndelay = 0;
c = getch();
if ( c == 'Q' ) break;
if ( c == ' ' ) dir = -dir;
if ( c == 'f' && delay > 2 ) ndelay = delay/2;
if ( c == 's' ) ndelay = delay * 2 ;
if ( ndelay > 0 )
set_ticker( delay = ndelay );
}
endwin();
return 0;
}
void move_msg(int signum)
{
signal(SIGALRM, move_msg); /* reset, just in case */
move( row, col );
addstr( BLANK );
col += dir; /* move to new column */
move( row, col ); /* then set cursor */
addstr( MESSAGE ); /* redo message */
refresh(); /* and show it */
/*
* now handle borders
*/
if ( dir == -1 && col <= 0 )
dir = 1;
else if ( dir == 1 && col+strlen(MESSAGE) >= COLS )
dir = -1;
}
bounce2d.c - More advanced version of bounce1d, instead of moving in a completely linear fashion, movement in two directions is now applied simultaneously. MATH.
#include
#include
#include "bounce.h"
struct ppball the_ball ;
/** the main loop **/
void set_up();
void wrap_up();
int main()
{
int c;
set_up();
while ( ( c = getchar()) != 'Q' ){
if ( c == 'f' ) the_ball.x_ttm--;
else if ( c == 's' ) the_ball.x_ttm++;
else if ( c == 'F' ) the_ball.y_ttm--;
else if ( c == 'S' ) the_ball.y_ttm++;
}
wrap_up();
}
void set_up()
/*
* init structure and other stuff
*/
{
void ball_move(int);
the_ball.y_pos = Y_INIT;
the_ball.x_pos = X_INIT;
the_ball.y_ttg = the_ball.y_ttm = Y_TTM ;
the_ball.x_ttg = the_ball.x_ttm = X_TTM ;
the_ball.y_dir = 1 ;
the_ball.x_dir = 1 ;
the_ball.symbol = DFL_SYMBOL ;
initscr();
noecho();
crmode();
signal( SIGINT , SIG_IGN );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
refresh();
signal( SIGALRM, ball_move );
set_ticker( 1000 / TICKS_PER_SEC ); /* send millisecs per tick */
}
void wrap_up()
{
set_ticker( 0 );
endwin(); /* put back to normal */
}
void ball_move(int signum)
{
int y_cur, x_cur, moved;
signal( SIGALRM , SIG_IGN ); /* dont get caught now */
y_cur = the_ball.y_pos ; /* old spot */
x_cur = the_ball.x_pos ;
moved = 0 ;
if ( the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1 ){
the_ball.y_pos += the_ball.y_dir ; /* move */
the_ball.y_ttg = the_ball.y_ttm ; /* reset*/
moved = 1;
}
if ( the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1 ){
the_ball.x_pos += the_ball.x_dir ; /* move */
the_ball.x_ttg = the_ball.x_ttm ; /* reset*/
moved = 1;
}
if ( moved ){
mvaddch( y_cur, x_cur, BLANK );
mvaddch( y_cur, x_cur, BLANK );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
bounce_or_lose( &the_ball );
move(LINES-1,COLS-1);
refresh();
}
signal( SIGALRM, ball_move); /* for unreliable systems */
}
int bounce_or_lose(struct ppball *bp)
{
int return_val = 0 ;
if ( bp->y_pos == TOP_ROW ){
bp->y_dir = 1 ;
return_val = 1 ;
} else if ( bp->y_pos == BOT_ROW ){
bp->y_dir = -1 ;
return_val = 1;
}
if ( bp->x_pos == LEFT_EDGE ){
bp->x_dir = 1 ;
return_val = 1 ;
} else if ( bp->x_pos == RIGHT_EDGE ){
bp->x_dir = -1;
return_val = 1;
}
return return_val;
}
bounce.h - The accompanying header to bounce1d and bounce2d
/* bounce.h */
/* some settings for the game */
#define BLANK ' '
#define DFL_SYMBOL 'o'
#define TOP_ROW 5
#define BOT_ROW 20
#define LEFT_EDGE 10
#define RIGHT_EDGE 70
#define X_INIT 10 /* starting col */
#define Y_INIT 10 /* starting row */
#define TICKS_PER_SEC 50 /* affects speed */
#define X_TTM 5
#define Y_TTM 8
/** the ping pong ball **/
struct ppball {
int y_pos, x_pos,
y_ttm, x_ttm,
y_ttg, x_ttg,
y_dir, x_dir;
char symbol ;
} ;
bounce_async.c and bounce_aio.c are above my head, currently. Here they are, respectively. Hopefully we will dissect these in class.
#include
#include
#include
#include
/* The state of the game */
#define MESSAGE "hello"
#define BLANK " "
int row = 10; /* current row */
int col = 0; /* current column */
int dir = 1; /* where we are going */
int delay = 200; /* how long to wait */
int done = 0;
main()
{
void on_alarm(int); /* handler for alarm */
void on_input(int); /* handler for keybd */
void enable_kbd_signals();
initscr(); /* set up screen */
crmode();
noecho();
clear();
signal(SIGIO, on_input); /* install a handler */
enable_kbd_signals(); /* turn on kbd signals */
signal(SIGALRM, on_alarm); /* install alarm handler */
set_ticker(delay); /* start ticking */
move(row,col); /* get into position */
addstr( MESSAGE ); /* draw initial image */
while( !done ) /* the main loop */
pause();
endwin();
}
void on_input(int signum)
{
int c = getch(); /* grab the char */
if ( c == 'Q' || c == EOF )
done = 1;
else if ( c == ' ' )
dir = -dir;
}
void on_alarm(int signum)
{
signal(SIGALRM, on_alarm); /* reset, just in case */
mvaddstr( row, col, BLANK ); /* note mvaddstr() */
col += dir; /* move to new column */
mvaddstr( row, col, MESSAGE ); /* redo message */
refresh(); /* and show it */
/*
* now handle borders
*/
if ( dir == -1 && col <= 0 )
dir = 1;
else if ( dir == 1 && col+strlen(MESSAGE) >= COLS )
dir = -1;
}
/*
* install a handler, tell kernel who to notify on input, enable signals
*/
void enable_kbd_signals()
{
int fd_flags;
fcntl(0, F_SETOWN, getpid());
fd_flags = fcntl(0, F_GETFL);
fcntl(0, F_SETFL, (fd_flags|O_ASYNC));
}
And
#include
#include
#include
#include
#include
/* The state of the game */
#define MESSAGE "hello"
#define BLANK " "
int row = 10; /* current row */
int col = 0; /* current column */
int dir = 1; /* where we are going */
int delay = 200; /* how long to wait */
int done = 0;
struct aiocb kbcbuf; /* an aio control buf */
main()
{
void on_alarm(int); /* handler for alarm */
void on_input(int); /* handler for keybd */
void setup_aio_buffer();
initscr(); /* set up screen */
crmode();
noecho();
clear();
signal(SIGIO, on_input); /* install a handler */
setup_aio_buffer(); /* initialize aio ctrl buff */
aio_read(&kbcbuf); /* place a read request */
signal(SIGALRM, on_alarm); /* install alarm handler */
set_ticker(delay); /* start ticking */
mvaddstr( row, col, MESSAGE ); /* draw initial image */
while( !done ) /* the main loop */
pause();
endwin();
}
/*
* handler called when aio_read() has stuff to read
* First check for any error codes, and if ok, then get the return code
*/
void on_input(int s)
{
int c;
char *cp = (char *) kbcbuf.aio_buf; /* cast to char * */
/* check for errors */
if ( aio_error(&kbcbuf) != 0 )
perror("reading failed");
else
/* get number of chars read */
if ( aio_return(&kbcbuf) == 1 )
{
c = *cp;
if ( c == 'Q' || c == EOF )
done = 1;
else if ( c == ' ' )
dir = -dir;
}
/* place a new request */
aio_read(&kbcbuf);
}
void on_alarm(int s)
{
signal(SIGALRM, on_alarm); /* reset, just in case */
mvaddstr( row, col, BLANK ); /* clear old string */
col += dir; /* move to new column */
mvaddstr( row, col, MESSAGE ); /* draw new string */
refresh(); /* and show it */
/*
* now handle borders
*/
if ( dir == -1 && col <= 0 )
dir = 1;
else if ( dir == 1 && col+strlen(MESSAGE) >= COLS )
dir = -1;
}
/*
* set members of struct.
* First specify args like those for read(fd, buf, num) and offset
* Then specify what to do (send signal) and what signal (SIGIO)
*/
void setup_aio_buffer()
{
static char input[1]; /* 1 char of input */
/* describe what to read */
kbcbuf.aio_fildes = 0; /* standard intput */
kbcbuf.aio_buf = input; /* buffer */
kbcbuf.aio_nbytes = 1; /* number to read */
kbcbuf.aio_offset = 0; /* offset in file */
/* describe what to do when read is ready */
kbcbuf.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
kbcbuf.aio_sigevent.sigev_signo = SIGIO; /* send sIGIO */
}
This chapter contained almost as much information as the preceding 6 chapters. Sometimes I wonder if the author to this book finds joy in anything since he obviously has attained supreme knowledge.
==3/13/14==
""
==3/20/14==
Today we continued with Chapter 8, adding to the fork concept. Using fork4 we played with wait() and added some interesting use of exec(). in this case we used execl().
#include
#include
#include
#include
int main(int argc, char **argv)
{
pid_t me, you;
char input, *fname;
FILE *fptr;
int i, j, data[100][2], rank = 0, numproc = 0;
int pidlist[5];
for(i=0; i<100; i++)
{
data[i][0] = i * i;
}
pidlist[0] = getpid();
for(i = 1; i <= 4; i++)
{
if(pidlist[0] == getpid())
{
rank = rank + 1;
pidlist[i] = fork();
}
}
if (getpid() == pidlist[0])
{
printf("I am PID %i, my child processes are: ", pidlist[0]);
for(i=1; i<=4; i++)
printf("%i ", pidlist[i]);
printf("\n");
// could put code to wait for child process termination here
for(i = 0; i < rank; i++)
{
you = wait(&j);
printf("child PID %d has finished with status %d\n",you,j);
}
}
else
{
if(rank==2){
execl("/bin/ls","ls","-l",NULL);
}
me = getpid();
printf("I am child %i (pid %i), so I will process ", rank, me);
printf("elements %i-%i ...\n", ((rank*25)-25), ((((rank+1)*25)-1)-25));
for(i = ((rank*25)-25); i < (((rank+1)*25)-25); i++)
data[i][1] = data[i][0] * rank;
fname = (char *) malloc (sizeof(char) * 8);
sprintf(fname, "rank%i", rank);
fptr = fopen(fname, "w");
fprintf(fptr, "%i\n", (rank*25)-25);
fprintf(fptr, "%i\n", (((rank+1)*25)-1)-25);
for(i = rank*25-25; i < ((rank+1)*25)-25; i++)
fprintf(fptr, "%i\t%i\n", data[i][0], data[i][1]);
fclose(fptr);
sleep(rank * 2+60);
}
return(0);
}