Most of assignment 3 is done now.

TODO: implement the other switch cases in gup_handler().
parent 4c224831
......@@ -19,18 +19,18 @@ ifdef PROFILE
CFLAGS += -pg
endif
fishbones: fishbones.o
fishbones: fishbones.o logger.o
$(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
clean:
rm -f fishbones.o fishbones $(PROG).tar.gz
rm -f *.o child.log* fishbones $(PROG).tar.gz
rm -Rf logs/
rm -Rf $(PROG)/
tarball:
$(MAKE) clean
$(MKDIR) $(PROG)
$(CP) * report/report.pdf $(PROG) 2> /dev/null || true
$(CP) * screenrc report/report.pdf $(PROG) 2> /dev/null || true
$(PACK) $(PROG).tar.gz $(PROG)/*
$(RM) $(PROG)
......@@ -38,3 +38,4 @@ tarball:
$(CC) -c $(CFLAGS) -o $@ $<
fishbones.o: fishbones.c
logger.o: logger.c
f a b f c d P e g P x x q
fabfcdPegPxxq
......@@ -6,28 +6,96 @@
#include <errno.h>
#include <string.h>
static void gup(FILE * log1, FILE * log2, int pipefd[2], int cpid)
#include "logger.h"
#define STRING_LENGTH (512)
static void
gup( log_handler * logs, int pipefd[2], int cpid);
static void
gup_handler( char c, int kids, int pipefd[2], log_handler * logs )
{
char buf[STRING_LENGTH+1], str[256];
pid_t cpid;
switch( c )
{
case 'q':
(void) sprintf(str, "Child %d normal exit\n", kids);
write_to_all_logs(logs, str);
close_all_logs(logs);
exit(EXIT_FAILURE);
break;
case 'f':
kids++;
// When you fork, be sure to print the process id of the child
// (if the fork succeeds) and an error message otherwise
cpid = fork();
if( cpid == -1 )
{
perror("fork");
exit(EXIT_FAILURE);
}
if( cpid == 0 )
{
// Child reads from pipe
gup(logs, pipefd, kids);
close_all_logs(logs);
_exit(EXIT_SUCCESS);
}
else
{
// Parent writes buffer to child
if( fgets(buf, STRING_LENGTH, stdin) )
if( !write(pipefd[1], buf, strlen(buf)) )
perror("pipe write");
// Close unused read end
close(pipefd[0]);
close(pipefd[1]);
wait(NULL);
close_all_logs(logs);
exit(EXIT_SUCCESS);
}
}
}
static void
gup(log_handler * logs, int pipefd[2], int cpid)
{
FILE * log3;
char c;
// Put any required declarations and initialisations here
if( !logs || !pipefd )
return;
// Close unused write end
close(pipefd[1]);
// Report your existence
fprintf(log1, "This is child number %d\n", cpid);
fprintf(log2, "This is child number %d\n", cpid);
// just for sure - open one more log file ...
log3 = fopen("child.log3", "wt+");
setvbuf(log3, NULL, _IOLBF, BUFSIZ);
// log3 is line buffered - a line of output is written
// immediately on encountering an end-of-line
fprintf(log3, "This is child number %d\n", cpid);
setvbuf(open_log("child.log3", "wt+", logs), NULL, _IOLBF, BUFSIZ);
// Report your existence
char * str = malloc(256 * sizeof(char *));
strcpy(str, "This is child number %d\n");
(void) sprintf(str, str, cpid);
write_to_all_logs(logs, str);
char * str_read = "Child %d read character %c '%x'\n";
char c;
while( read(pipefd[0], &c, 1) > 0 )
{
......@@ -37,131 +105,65 @@ static void gup(FILE * log1, FILE * log2, int pipefd[2], int cpid)
// an end-of-file (read returns zero), end your program
// with an exit(1)
fprintf(log1, "Child %d read character '%x'\n", cpid, c);
fprintf(log2, "Child %d read character '%x'\n", cpid, c);
fprintf(log3, "Child %d read character '%x'\n", cpid, c);
if( write(STDOUT_FILENO, &c, 1) == -1 )
{
fprintf(stderr, "write error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
(void) sprintf(str, str_read, cpid, c, c);
write_to_all_logs(logs, str);
// process the character here
gup_handler(c, cpid, pipefd, logs);
}
char nl = '\n';
if( write(STDOUT_FILENO, &nl, 1) == -1 )
{
fprintf(stderr, "write error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(log1, "Child %d normal exit \n", cpid);
fprintf(log2, "Child %d normal exit \n", cpid);
fprintf(log3, "Child %d normal exit \n", cpid);
fclose(log1);
fclose(log2);
fclose(log3);
}
#define STRING_LENGTH (512)
int main(int argc, char ** argv)
static void
process_handler( log_handler * logs )
{
FILE * log1;
FILE * log2;
char buf;
int kids = 0;
int pipefd[2];
log1 = fopen("child.log1", "wt+");
log2 = fopen("child.log2", "wt+");
setvbuf(log2, NULL, _IONBF, BUFSIZ);
// So log1 is buffered; log2 is not buffered, which means that output
// to log2 is written immediately.
// create the pipe somewhere around here (why?).
// create the pipe somewhere around here (why?).
// remember to test for success!!
if( pipe(pipefd) == -1 )
{
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t cpid;
while( (buf = getchar()) )
{
// You can now choose to use only the first character in the
// string (inString[0]), or the entire string (how would you test
// that?).
// Anyway, read a character, echo it to both log files
// and write it into the pipe (unless you have to call fork)
printf("%c", buf);
fflush(stdout);
char * str = malloc(256 * sizeof(char)),
* str_read = "Parent %d read character %c '%x'\n";
switch( buf )
{
case 'q':
goto close_logs;
break;
strcpy(str, "This is the parent process %d\n");
(void) sprintf(str, str, 0);
write_to_all_logs(logs, str);
case 'f':
char c;
int kids = 0;
kids++;
while( (c = getchar()) )
{
// Anyway, read a character, echo it to both log files
// and write it into the pipe (unless you have to call fork)
// When you fork, be sure to print the process id of the child
// (if the fork succeeds) and an error message otherwise
cpid = fork();
if( cpid == -1 )
{
perror("fork");
exit(EXIT_FAILURE);
}
if( cpid == 0 )
{
// Child reads from pipe u1
gup(log1, log2, pipefd, kids);
_exit(EXIT_SUCCESS);
}
else
{
/* Parent writes to pipe */
//write(pipefd[1], buf, len);
// Close unused read end
close(pipefd[0]);
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
default:
printf("buf => default => exit\n");
//exit(EXIT_SUCCESS);
fflush(stdout);
goto close_logs;
}
(void) sprintf(str, str_read, 0, c, c);
write_to_all_logs(logs, str);
gup_handler(c, kids, pipefd, logs);
}
}
// normal end of program
close_logs:
int
main( void )
{
// log1 is buffered; log2 is not buffered
// which means that output to log2 is
// written immediately.
log_handler * logs = create_logger();
(void) open_log("child.log1", "wt+", logs);
setvbuf(open_log("child.log2", "wt+", logs), NULL, _IONBF, BUFSIZ);
process_handler(logs);
// close all open log files
fclose(log1);
fclose(log2);
close_all_logs(logs);
return 0;
return EXIT_SUCCESS;
}
/*
* File logger abstraction layer
*
* Created by: Sander van Veen <sandervv@gmail.com>,
* Taddeüs Kroes <taddeuskroes@gmail.com>
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "logger.h"
/*
* Initialize a new log handler
*/
log_handler *
create_logger( )
{
log_handler * log = malloc(sizeof(log_handler));
log->list = NULL;
log->count = 0;
return log;
}
/*
* Open or create a log file, like fopen(), and add the opened file
* pointer to the log handler.
*/
FILE *
open_log( const char * filename, const char * access, log_handler * log )
{
if( !log )
return NULL;
log->list = realloc(log->list, (log->count+1) * sizeof(FILE *));
log->list[log->count] = fopen(filename, access);
return log->list[log->count++];
}
/*
* Close a specific log file, which was opened by open_log().
*
* See also:
* <open_log>, <close_all_logs>
*/
void
close_log( FILE * file, log_handler * log )
{
if( !file || !log )
return;
fclose(file);
FILE ** cur = log->list;
// Find open file in logger list
while( *cur != file && cur++ );
if( cur )
{
FILE ** end = log->list + log->count;
free(*cur);
*cur = NULL;
for( ; cur < end; cur++ )
*cur = *(cur+1);
log->count--;
}
}
/*
* Close all log files, which was opened by open_log().
*
* See also:
* <open_log>, <close_log>
*/
void
close_all_logs( log_handler * log )
{
if( !log )
return;
FILE ** cur = log->list;
FILE ** end = cur + log->count;
for( ; cur < end; cur++ )
{
fclose(*cur);
}
free(log->list);
free(log);
}
void write_to_all_logs( log_handler * log, const char * str )
{
if( !log || !str )
return;
FILE ** cur = log->list;
FILE ** end = cur + log->count;
for( ; cur < end; cur++ )
fwrite(str, strlen(str), sizeof(char), *cur);
}
#include <stdio.h>
#include <sys/types.h>
typedef struct log_handler
{
/*
* List of opened log files.
*/
FILE ** list;
/*
* Total count of currently opened logs.
*/
int count;
} log_handler;
log_handler * create_logger( );
FILE * open_log( const char * filename, const char * access, log_handler * log );
void close_log( FILE * file, log_handler * log );
void close_all_logs( log_handler * log );
void write_to_all_logs( log_handler * log, const char * str );
bindkey ^c at "#" kill
split -v
screen watch cat child.log1
focus
split -v
screen watch cat child.log2
focus
screen watch cat child.log3
#!/bin/bash
if [ "`which screen`" = '' ]; then
echo "GNU screen is missing. I'll now trying to install screen using apt-get.";
echo "The installation of GNU screen requires sudo-rights: ";
sudo apt-get install screen ;
fi;
screen -c screenrc
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment