----------------------- Lab #02 for CST8165 due September 17, 2007 (Week 3) ----------------------- -Ian! D. Allen - idallen@idallen.ca - www.idallen.com Remember - knowing how to find out an answer is more important than memorizing the answer. Learn to fish! RTFM! (Read The Fine Manual) Global weight: 2% of your total mark this term. Due date: before 23h59 Monday September 17 The deliverables for this exercise are to be submitted online in the Linux Lab T127 using the "cstsubmit" method described in the exercise description, below. No paper; no email; no FTP. Late-submission date: I will accept without penalty exercises that are submitted late but before 13h00 on Tuesday, September 18. After that late-submission date, the exercise is worth zero marks. Exercises submitted by the *due date* will be marked online and your marks will be sent to you by email after the late-submission date. Exercise Synopsis and Objectives: 1. Remember how to use Makefiles 2. Remember how to structure programs in multiple .c/.h files 3. Learn to create C preprocessor (cpp) output via "cc -E" Enhance your Lab #1 Makefile and server code. Test everything. Where to work: Submissions must make, compile, and run cleanly in the T127 Linux Lab, though you are free to work on them anywhere you like. Dependencies: You must have a working Makefile that can build server2. Consult your instructor for assistance in getting a broken Makefile to work before you begin this lab. This lab *adds* targets to your existing Makefile. You should not delete any of the existing targets created in previous labs. Part I - looking at C pre-processor output ------------------------------------------ The server2.c code we are working on has a "will never be executed" warning on code that is clearly being executed. To find out the cause of this warning, we need to look at what changes the C preprocessor has made to our source file before the compiler sees it. 1) Add the following variable near the top of the Makefile from Lab #1: CF2 = $(CFLAGS) -E 2) Find the explanation of what the "-E" option does in the gcc man page. Read it. Note that the output of "cc -E" is preprocessor output - it is text C code. The output is not an object file and is not a binary executable! Why are there no "#include", "#define", or "#ifdef" statements in the output of "cc -E"? 3) To the bottom of your Makefile, add a new Makefile target "serverX.c" with dependency "server2.c" that runs gcc with the $(CF2) options to pre-process source file server2.c into output source file "serverX.c". Unlike last lab, where you could use the default Makefile actions to call the gcc compiler, in this case you *must* specify the full gcc compile line, including specifying the output file, so that you can pass the $(CF2) options to gcc and capture the preprocessor output. 4) Add serverX.c to the list of files to be cleaned in "make clean". (Test it!) 5) Run "make serverX.c" to run the gcc pre-processor to create source file "serverX.c" from server2.c using the $(CF2) flags. Confirm that all the CFLAGS options are used, plus the new -E option. Confirm that the created file "serverX.c" is C source code - the output of running the C preprocessor on the server2.c source file. 6) Look at the bottom 60 lines of the serverX.c source file, where the serv_addr.sin_port and htons() code gives "unreachable" warnings. (You saw this htons() warning "will never be executed" in the previous lab - it was the only warning you couldn't get rid of.) Note what a mess the htons() code has expanded into after going through the gcc pre-processor! The resulting unreachable code in the "if" statement is the reason this line generates an unreachable code warning. You would never know this unless you looked at the output of the C pre-processor. Looking at pre-processor output (using -E on Unix) is often the only way to know what code you are actually compiling, and why some compile errors and warnings happen. 6a) Experiment temporarily with gcc options to find out which compiler flag is causing the htons() code to be expanded into the "unreachable code" line. (Hint: Removing one gcc option will cause htons() to be left unexpanded and untouched. Which option?) Do not remove the -Wunreachable-code warning as you experiment. 6b) After you have identified the gcc option that causes htons() to be expanded, restore the gcc options to their Lab 1 standard form, except, *remove* the "-g" option from the standard CFLAGS list. 7) Add a new Makefile target "serverX" that depends on "serverX.c". Rely on the the default "make" rules to build this target from source. Your Makefile will now have these five targets: all server2 clean serverX.c serverX 8) Add serverX to the list of files to be cleaned in "make clean". 9) Run "make serverX" to compile and create binary file "serverX". Run "make all" or "make server2" to create binary file "server2". Confirm that all the CFLAGS options are used in both cases. Make sure that "-g" is *not* used for this step. 10) Run "cmp -l -b server2 serverX" and note the one-byte difference in the two binary files. Why is that byte different? To help understand the output of "cmp -l -b", try this: $ echo "one two three" >a $ echo "one abc three" >b $ cmp -l -b a b Some system man pages don't document the -b option to "cmp" - look up other man pages on the Internet by searching for: man cmp or try "cmp --help". Old versions of cmp use "-c" instead. 10b) Put back the full set of CFLAGS options to gcc given in Lab 1. (Include all the options mentioned in Lab 1, including -g and -O.) Part II - cleaning up the error() function ------------------------------------------- The function "error()" included with the downloaded code is badly named. We need to rename it and move it into its own file, using these following few steps: 11) Create and compile this one-line source file: main(){ error("abc"); } Why doesn't the linker give a link error about the missing function named error()? If you deleted the static function error() from your server2.c source file, would the program still compile and link? Explain. 12) Rename your function "error()" to "myerror()" everywhere. 12a) Move the code for the myerror() function out of server2.c into its own source file named "myerror.c". 12b) Create the appropriate matching "myerror.h" file. For guidance, read the Notes file: header_files.txt 13) Fix the Makefile to rebuild server2 if myerror.c or myerror.h are updated. 14) Fix the Makefile to rebuild serverX if myerror.c or myerror.h are updated. Part III - The Tests -------------------- Here are some tests to run now to make sure your Makefile is correct. A later section shows how to run these tests in a "script" session. 15) $ make clean - anything created by the Makefile should be removed - are all the objects created by the Makefile removed? - typing "make clean" twice should not generate any error messages even if everything has been removed already 16) $ make clean all ; make all ; make all - is server2 built just once? 17) $ make clean ; make ; make ; make - is server2 built just once? 18) $ make clean all ; sleep 2 ; touch server2.c ; make all ; make all - is server2 built exactly twice? 19) $ make clean all ; sleep 2 ; touch myerror.c ; make all ; make all - is server2 built exactly twice? 20) $ make clean all ; sleep 2 ; touch myerror.h ; make all ; make all - is server2 built exactly twice? 21) $ make clean serverX.c ; make serverX.c - is serverX.c built just once? 22) $ make clean serverX ; make serverX - is serverX.c built from server2.c? - is serverX built just once? 23) $ make clean serverX ; sleep 2 ; touch server2.c ; make serverX serverX - is serverX built exactly twice? 24) $ make clean serverX ; sleep 2 ; touch myerror.c ; make serverX serverX - is serverX built exactly twice? 25) $ make clean serverX ; sleep 2 ; touch myerror.h ; make serverX serverX - is serverX built exactly twice? Capturing the tests using a script session ------------------------------------------ 26) Start a "script" session (man script) using my script cover and with output file "testing.txt": $ ~alleni/bin/script testing.txt This will save your terminal command lines and output into the given file name. Make sure you use my cover script, as shown above. Note: Your output file "testing.txt" will not contain the full results of your script session until you exit the subshell started by the script command. When you exit the subshell, script will tell you the name of the output file. See the next few steps: 27) Run the above Makefile tests #15-#25. 28) Test your myerror() code by starting your server2 using a privileged port argument number greater than zero and less than 1024 (e.g. 123). Make sure you see the error message: ERROR on binding: Permission denied Confirm that the error appears from perror() and that it appears on standard error (not on standard output). Why don't you have permission to bind to ports less than 1024 on Unix? 29) Run the same server2 netcat tests that you did for Lab #1. 30) Exit the script session subshell. Script will tell you the name of your script output file: $ exit Script done, file is testing.txt $ less testing.txt You may now examine your saved script session. 31) In a new file named "README.txt", summarize briefly the results of your testing. If any of your Makefile tests failed, or if the netcat test did not work properly, document which tests failed. If everything worked, say so. 32) Submit the files using the exact file names given below. No added programming comments are needed in these source files (yet). Submission ---------- A. At the top of each and every submitted file, as comments, create an Exterior Assignment Submission label following the directions from last week's lab. Every file must have a label; use comments as needed. B. For material you copy from other sources, credit the author and source, following the directions from last week's lab. C. Submit these files for marking as Exercise 02 using the following *single* cstsubmit command line: $ ~alleni/bin/cstsubmit 02 \ README.txt server2.c myerror.c myerror.h testing.txt Makefile See last week's lab for details on using cstsubmit. All file names must be spelled *exactly* as given above. Always submit *all* files any time you submit. Incorrect and past-cut-off-time submissions are worth zero marks. P.S. Did you spell all the assignment label fields and file names correctly?