Table of Contents

Jon VanZile's Opus

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	<stdio.h>
#include	<curses.h>

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	<stdio.h>
#include	<curses.h>

main()
{
	int	i;

	initscr();			/* turn on curses	*/
	   clear();			/* draw some stuff	*/
	   for(i=0; i<LINES; i++ ){		/* in a loop	*/
		move( i, i+i );
		if ( i%2 == 1 )
			standout();
		addstr("Hello, world");
		if ( i%2 == 1 )
		       standend();
	   }

	   refresh();			/* update the screen	*/
	   getch();			/* wait for user input	*/
	endwin();			/* reset the tty etc	*/
}

hello3.c

#include	<stdio.h>
#include	<curses.h>

main()
{
	int	i;

	initscr();
	   clear();
	   for(i=0; i<LINES; i++ ){
		move( i, i+i );
		if ( i%2 == 1 ) 
			standout();
		addstr("Hello, world");
		if ( i%2 == 1 ) 
			standend();
		sleep(1);
		refresh();
	   }
	endwin();
}

hello4.c

#include	<stdio.h>
#include	<curses.h>

main()
{
	int	i;

	initscr();
	   clear();
	   for(i=0; i<LINES; i++ ){
		move( i, i+i );
		if ( i%2 == 1 ) 
			standout();
		addstr("Hello, world");
		if ( i%2 == 1 ) 
			standend();
		refresh();
		sleep(1);
		move(i,i+i);			/* move back	*/
		addstr("             ");	/* erase line	*/
	   }
	endwin();
}

hello5.c

#include	<curses.h>

#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	<stdio.h>
#include	<signal.h>
// #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	<stdio.h>
#include        <sys/time.h>
#include        <signal.h>

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	<stdio.h>
#include	<signal.h>

#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	<stdio.h>
#include	<signal.h>
#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	<stdio.h>
#include	<curses.h>
#include	<signal.h>

/* 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	<curses.h>
#include	<signal.h>
#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	<stdio.h>
#include	<curses.h>
#include	<signal.h>
#include	<fcntl.h>

/* 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	<stdio.h>
#include	<curses.h>
#include	<signal.h>
#include	<aio.h>
#include	<string.h>

/* 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<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>

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

Portfolio

cprog