420 likes | 571 Views
Herbert G. Mayer, PSU CS Status 11/11/2013. CS 201 Computer Systems Programming Chapter 2 argc, argv, envp, system(), libs. argc argv envp. Syllabus. Definitions Samples of argc argv envp Possible argv[] Implementation? Sample envp Concatenate References s ystem()
E N D
Herbert G. Mayer, PSU CS Status 11/11/2013 CS 201Computer Systems ProgrammingChapter 2argc, argv, envp, system(),libs
Syllabus • Definitions • Samples of argc argv envp • Possibleargv[]Implementation? • Sample envp • Concatenate • References • system() • Sample Uses of system() • Unix Commands & C Libraries • Acknowledgment
Definitions • In C, the main()function returns an int result; the formal parameter list may be empty, or else contain the specification of command line parameters • In C++, the main()function also returns an inttype result; yet the formal parameter list must be specified as void, if it does not contain command line parameters • These are traditionally named argc, argv, and envp; on Apple platforms a fourth parameter can be specified, not surprisingly named “apple” • Environment variable names may be chosen freely, but “argc” and “argv” are tradition
Definitions int main( int argc, // specifies # in argv[] char * argv[], // list of parameters char * envp[] ) // all environment vars { // main . . . } //end main • Why specify argc? • To allow empty-string command line parameters • Cannot have a null environment variable
Definitions • argc • Specified as int argc, is main()’s first formal parameter • argc counts the number of command line arguments that argv[] holds for this current program execution • Includes the object program itself, hence must be >= 1 • argv • Specified as char ** argv, equivalently char * argv[] • is 2nd formal parameter of main(); optional; if specified, the first parameter argc must already be specified • argv is a pointer to the list of actual const string arguments • envp • Specified as char ** envp, equivalently char * envp[] • is 3rd formal and optional parameter of main() • Holds environment variables as string constants, plus the header: PATH=
C Quirks • Note that for argv[] an ancillary data structure is provided: argc • Thus it is possible –but not a good idea– to pass an empty string as one of the various command line arguments • And if your program scans for the “end of the list” by checking for the null string, your loop terminates checking the argv[] values too early • This is not possible with envp[], as no empty (null string) environment variable can be specified • Delicate point, but that is what system programming is all about!
Reverse-Print Command Line Args // output all command line arguments of a.out: // but in reverse order of command line int main( int argc, char * argv[] ) // ignore envp { // main printf( "%d command line args passed.\n", argc ); while( --argc > 0 ) { // pre-decrement skips a.out printf( "arg%d = \"%s\"\n", argc, argv[ argc ] ); } //end while } //end main [args] a.out 3 r 55 the command line entered 4 command line args passed. arg3 = "55" arg2 = "r" arg1 = "3"
Sample argc, argv • a.out 12 '.' "345" E "+" 0 • Number of command line arguments passed = 7 • This includes program name • argv[0] = a.out • argv[1] = 12 • argv[2] = . -- without single quote ‘ • argv[3] = 345 -- without double quote “ • argv[4] = E • argv[5] = + -- without double quote “ • argv[6] = 0 • Note that all matching “ and ‘ pairs are stripped away • All command args concatenated are = "12.345E+0" • Looks like the floating point number = 12.345
Possible argv[]Implementation? • How are such actual parameters passed to main() ? • Which tool passes them from the command line to the run-time-system? • Students think, design, discuss: • 1.) Will on-the-fly creation of assembler source program help? Assumes an assembly step to create another *.o • 2.) Will manipulation of stack, heap, code help, before or while loading provide the actual parameters? • 3.) Other possibilities? Discuss or email good ideas, and get extra credit!
Possible argv[] Implementation? • Your Unix shell executes the a.out command • Let’s say: a.out 100000 “9/12/2012” • The shell sees the command line, verifies that a.out exists and is executable, then loads your program, the shell does ??, executes your program, continues after exit • At the point of ?? some magic happens • All work to provide command line parameters is accomplished between shell command and execution • Clearly a.out may not be modified from run to run • So, sometimes argc, argv, envp are accessed during execution, other times not
Sample envp • The Unix shell command man setenv generates this output: • NAME • set, unset, setenv, unsetenv, export -shell built-in functions to determine the characteristics for environmental variables of the current shell and its descendents . . Much more • Current environment variables used in your Unix environment are tracked and can be output for any of your processes • Similar to char * argv[], envp is also a pointer to an array of 0 or more strings, followed by a null string • Each such string contains one of your process’ environment variables
Sample envp Version 1 in C++, skip • #include <iostream.h> // for: cin, cout, endl etc. • int main( int argc, char ** argv, char ** envp ) • { // main • int count = 0; • while( *envp ) { • cout << "environment variable" << ++count << “ = \"" • << *envp << '"' << endl; • ++envp; // or envp++ if you prefer • } //end while • cout << "Number of environment variables tracked = “ • << count << endl; • exit( 0 ); • } //end main
Sample envp Version 2 in C • int main( int argc, char ** argv, char * envp[] ) • { // main • int index = 0; • while( envp[ index ] ) { // OK to assume null-terminated strings • // print one environment variable at a time • printf( "envp[%d] = \"%s\"\n", index, envp[ index++ ] ); • } //end while • printf( "Number of environment vars = %d\n", index ); • exit( 0 ); • } //end main
Sample envp, Counting from 1 • environment variable 1 = "USER=herb" • environment variable 2 = "LOGNAME=herb" • environment variable 3 = "HOME=/u/herb" • environment variable 4 = "PATH=.:/usr/lang:/bin/sun4:/usr/etc:/vol/local/rhost/sun4/bin:/usr/ucb:/bin:/vol/local:/vol/local/bin:/vol/local/sun4/bin:/usr/ccs/bin:/usr/ccs:/vol/userlocal/bin:/usr/local/bin:/home/vads/VADS_location/bin" • environment variable 5 = "MAIL=/var/mail//herb" • environment variable 6 = "SHELL=/bin/csh" • environment variable 7 = "TZ=US/Pacific" • . . . And many more • environment variable 12 = "LC_MONETARY=en_US.ISO8859-1" • environment variable 13 = "LC_MESSAGES=C" • environment variable 14 = "LANG=en_US.UTF-8" • environment variable 15 = "SSH_CLIENT=50.53.47.189 50625 22" • environment variable 16 = "SSH_CONNECTION=50.53.47.189 50625 131.252.208.127 22" • environment variable 17 = "SSH_TTY=/dev/pts/33" • environment variable 18 = "TERM=xterm-256color" • environment variable 19 = "PWD=/u/herb/progs/args" • environment variable 20 = "term=vt100=” • Number of environment vars = 20
Concatenate • char g_string[ 100000 ]; // large enough to hold command line arguments • // return string pointing to concatenation of command line args, not 1st • char * cat_not_first( int argc, char * argv[] ) • { // cat_not_first • g_string[ 0 ] = (char)(0); // place null into first character • for ( int i = 1; i < argc; i++ ) { // don’t start at 0, for “a.out” • strcat( g_string, argv[ i ] ); • } //end for • return g_string; • } //end cat_not_first
References • http://crasseux.com/books/ctutorial/argc-and-argv.html • http://en.wikipedia.org/wiki/Main_function • http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fmainf.htm
system( “string” ) • The system() function is a C function, NOT a shell command; causes error as a shell command • Available in library #include <stdlib.h> • Passes its sole string parameter to the shell, as if that same string had been typed via a shell command • Exit status of last completed command is passed back to the invoking C program • If a null string is given, system( “” ) checks if the shell exists and then terminates
system( “string” ) • Executed command returns with exit status in waitpid(3) format, which is passed to the invoking C program • waitpid() reqires: #include <sys/types.h> and #include <sys/wait.h> • waitpidsuspends execution of calling program until status of terminated child process is available --any of its child processes
Sample Uses of system() • Write a C program, using system() that prints the Unix man page for system() • Just as if command “man system”had been typed as a Unix shell command • Sample shown below: • #include <stdlib.h> • int main() • { // main • system( "man system" ); • . . . • } //end main
Sample Uses of system() Write a C program using system()that: • Assumes the current working directory is arg_test • Changes directory from . named arg_test, to .. one level up • Then lists all files in that .. directory via: ls –la • Changes back to directory arg_test • And finally shows all files listed in arg_test • #include <stdlib.h> • int main( void ) • { // main • // assume execution in directory arg_test • system( "cd ..; ls -la; cd arg_test; ls -la" ); • } //end main
Sample Uses of system() • C program that prints the current working directory by using system(), specifying string literal “pwd” • Or by passing-in the command through argv[1] • #include <stdlib.h> • #define command "pwd" • // invoke via: a.out "pwd”, or via: a.out pwd • int main( int argc, char * argv[] ) • { // main • printf( "using string const \"pwd\"\n" ); • system( command ); • printf( "using argv[1] = %s\n”, argv[1] ); • system( argv[1] ); • system( "argv[1]" ); // this would be an error! • // the string "argv[1]" is NOT a valid shell command • } //end main
Tricky Use of system() • Write a C program using system() that prints the current date/time • Then compiles and runs its own source sys7.c • Watch out what happens with C file sys7.c: • #include <stdlib.h> • #include <time.h> • // file name: sys7.c • int main( /* void */ ) • { // main • time_t cur_time = time( '\0' ); • printf( "%s", asctime( localtime( & cur_time ) ) ); • printf( ”Compile and execute sys7.c\n" ); • system( "gcc sys7.c; a.out" ); • printf( "U r rich when u get here \n" ); • } //end main
Unix Commands, C Libraries • C and C++ are mature languages, widely used, yet offering limited high-level language facilities • No array assignments • No lexically nested functions or procedures • Limited built-in functions, hence the numerous libraries • Libraries still render the C language rich and versatile in use; some Unix libs, commands are ubiquitous, e.g.: • ps command • setenv command • signal.h lib • stdlib.h lib • sys/types.h lib • time.h lib -- use for HW3 • time command -- use for HW3
Unix Command ps • Name: ps • Purpose: print status of current processes • Functions: prints information about active processes. Without options, lists processes with same effective user ID and controlling terminal as invoker • Output contains process ID, terminal ID, cumulative execution time, and command name • Options are numerous: ps [-aAcdefjlLPyZ] [-g grplist] [-n namelist] [-o format] [-p proclist] [-s sidlist] [-t term] [-u uidlist] [-U uidlist] [-G gidlist] [-z zonelist]
Unix Command setenv • Name: setenv • Purpose: reports of environment variables for the current process and all its descendents • Function: various commands are set unset unsetenv export • Sample use without arguments: • USER=herb • LOGNAME=herb • HOME=/u/herb • PATH=.:/usr/lang:/bin ... long list of paths • MAIL=/var/mail//herb • SHELL=/bin/csh • TZ=US/Pacific • LC_CTYPE=en_US.ISO8859-1 • LC_COLLATE=en_US.ISO8859-1 ... etc.
$PATH, etc. on PSU’s Odin, Sirius • On Unix shell, issue the command man shell_builtins and learn about several interesting commands, e.g.: • alias • echo $PATH • setenv • Command echo $PATH shows the one PATH= line that your program did output –plus many more– scanning through envp[] • That was the line starting with PATH= . /user/ . . . • Or just issue command $PATH and observe the error at the end • Again you will see a path for all directories searched, in order, to resolve a command --or finding a file-- you specified • Command setenvwithout arguments will provide information that your program outputs, when scanning through envp[] • What if you wish to add directory /u/herb/progsto your search path $PATH? • Issue command setenv PATH $PATH\:/u/herb/progs, will add /u/herb/progsat the end of existing path
C Library signal • Name: #include <signal.h> • Purpose: provide signal management for application processes • Key Functions with 1st argument sig: signal() sigset() sighold() sigrelse() sigignore() sigpause() • Signals are tools for asynchronous interprocess communication in Unix. Signal is sent to process or thread of the same process to notify that a specific event (the signal) has occurred. Some of the functions set, others remove etc. the event recording. If process has registered a signal handler, that handler is executed upon signal set
C Library stdlib • Name: #include <stdlib.h> • Purpose: defines key functions and macros • Key Functions: exit() malloc() printf() ...
C Library types • Name: #include <sys/types.h> • Purpose: defines 100s of types for 32-bit and 64-bit target systems • Key Functions: clock_t time_t pid_t size_t _CHAR_IS_SIGNED (or UNSIGNED)
C Library time • Name: #include <time.h> • Purpose: tracking run-time cycles • Key Functions: localtime() returns: struct tm* single argument: const * clock asctime() returns: char * single argument: const struct tm* • time_t cur_time = time( '\0' ); • printf( "%s", asctime( localtime( & cur_time ) ) );
C Library time clock_t is type to track system ticks treat as if it were a numeric type clock() function, returning ticks clock_t CLOCKS_PER_SEC clock_t constant used to convert clock ticks into seconds • clock_t start, end, total; // to measure start time etc. • . . . • start = clock(); // take first measurement • . . . // do compute-intensive work • end = clock(); // take final measurement • total = end - start; // track time for work • printf( "ticks = %10u, seconds = %f\n", total, • (double)( (double)total / (double)CLOCKS_PER_SEC ) );
Unix Command time arg • Command name: time arg • Purpose: measures the time of any optional Unix command arg • Function: outputs the timing statistics to standard error, as • elapsed time, ie. wall-clocktime • user CPU time, in float format • system CPU time, in float format • and more . . .
Unix Command time a.out > time ./a.out...real 1m41.911suser 1m39.816ssys 0m1.957s Real time: Elapsed wall clock time 1 min. 41 sec. User time: User CPU time 1 min. 39 sec System time: System overhead CPU time 0 min. 1.9 sec.
Traditional Unix Command time > time -p ./a.out...real 101.76user 99.67sys 1.94 Real time: Elapsed wall clock time 101.76 sec. User time: User CPU time 99.67 sec System time: System overhead CPU time 1.94 sec.
Unix C Shell Command time > time a.out...99.0u 1.0s 1:41 98% 0+0k 0+0io 0pf+0w Default format: '%Uu %Ss %E %P %I+%Oio %Fpf+%Ww' where: • %U: User CPU time in seconds • %S: System CPU time in seconds • %E: Elapsed wall-clock time in minutes and seconds • and more ...
Other Unix Commands • isainfo –v shows architecture detail, 32/64 bit • –v verbose version gives max isainfo • uname –p prints product name, e.g.: sparc • arch manufacturer marketing name, e.g.: sun4
References The C Programming Language, Second Edition: Brian W Kernighan and Dennis M. Richie, Prentice Hall, Englewood Cliffs, New Jersey 07632 time(1) man page: http://linux.die.net/man/1/time csh(1) man page: http://linux.die.net/man/1/csh
Acknowledgment • Hin Yun Lee graciously contributed the pages about the Unix and Linux time command during the winter quarter 2013, gratefully included here