Exercises
Write a simple version of the date command that accepts a format string on the command line and uses it to format and print the current time.
When a file is more than six months old, ‘ls -l’ uses a simpler format for printing the modification time. The GNU version of ls.c uses this computation:
4449 struct timespec six_months_ago; ... 4458 /* Consider a time to be recent if it is within the past six months. 4459 A Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds 4460 on the average. Write this value as an integer constant to 4461 avoid floating point hassles. */ 4462 six_months_ago.tv_sec = current_time.tv_sec - 31556952 / 2; 4463 six_months_ago.tv_nsec = current_time.tv_nsec;Compare this to our example computation for computing the time six months in the past. What are the advantages and disadvantages of each method?
Write your own version of strftime(). Don’t worry about locale differences; simply use the English names for the months and the days of the week. Be sure not to overflow the input buffer.
Compare your version to the author’s, available on GitHub.13
Write a simple version of the touch command that changes the modification time of the files named on the command line to the current time.
Add an option to your touch command that accepts a date and time specification on the command line and uses that value as the new modification time of the files named on the command line. Can you use strptime()?
Add another option to your version of touch that takes a file name and uses the modification time of the given file as the new modification time for the files named on the command line.
Enhance ch-general1-sortemp.c to sort a separate array of pointers that point into the array of employees.
Add options to ch-general1-sortdir.c to sort by inode number, modification time, access time, and size. Add a “reverse option” such that time-based sorts make the most recent file first and other criteria (size, inode) sort by largest value first.
Write a simple version of the chown command. Its usage should be
chown user [: group ] files ...
Here, user and group are user and group names representing the new user and group for the named files. The group is optional; if present, it is separated from the user by a colon.
To test your version on a GNU/Linux system, you will have to work as root. Do so carefully!
Enhance your chown to allow numeric user or group numbers, as well as names.
Write functions to copy user and group structures, including pointed-to data. Use malloc() to allocate storage as needed.
Write a specialized user-lookup library that reads the entire user database into a dynamically allocated array. Provide fast lookup of users, by both user ID number and name. Be sure to handle the case in which a requested user isn’t found.
Do the same thing for the group database.
Enhance ch-general1-groupinfo.c to also examine the gr_name field of the struct group.
Write a stat program that prints the contents of the struct stat for each file named on the command line. It should print all the values in human-readable format: time_t values as dates and times, uid_t and gid_t values as the corresponding names (if available), and the contents of symbolic links. Print the st_mode field the same way that ls would.
Compare your program to the GNU Coreutils stat program, both by comparing outputs and by looking at the source code.
Get a cup of coffee (or tea), sit down, and read the stty(1) manpage, which describes the myriad options and settings for terminals. When your head stops spinning, think about the history of terminal devices, from physical teletypes through video terminals and on to windowing systems. Which of the features that are still supported today are mostly irrelevant? Which are still necessary for day-to-day use?
