Other Functions Some other functions will be used by programs or symbol table extensions that want to add additional forms of interaction (such as a GUI or database access). Table A.1 describes these functions. TABLE A.1 Other Symbol Table Functions Function Description st_set() This function takes a smart pointer, two strings, a variable name, and a value, and assigns the value to the variable after looking up the variable in the symbol table pointed to by the smart pointer. st_walk() These two functions are used to traverse st_walk_next() a symbol table, stopping at each variable or member. st_lookup() This function is used to find a given identifier within a symbol table. st_find_attrib() This function is used to retrieve the value of an attribute associated with a symbol table or subset. st_tostring() These two functions invoke the text st_from_string() conversion meth- ods associated with a basetype. userchange main() This section covers the main() function piece-by-piece, starting with the declarations. We need to declare main() in the traditional manner with argc and argv to have access to the command-line parameters. main(argc,argv) int argc; char *argv[]; /* or char **argv */ { passwd_t options; char command[256]; FILE *pipe; FILE *rc_file; st_show_opt_t st_show_options; In the first block, we read a configuration file. In this case, the file will be named ./userchange.rc in the current directory. In a typical application, you might want to try reading a couple different files, /etc/userchange.rc and $(HOME)/userchange.rc in succession. We must open the file ourselves; the symbol table library does not do that for us. In the event of failure, we will simply skip the remainder of this block of code. Linux Programming U NLEASHED 758 4772316072 App A 7/26/99 2:15 PM Page 758 The options symbol table, options_st, was previously defined to include a random assortment of variables, including the hostname for remote operation, the operation to be performed, the debugging level for the symbol table package, the passwd structure that contains all the password fields we can change, and others. A call to st_read_stream() does the actual work. We pass in three arguments: The stream we already opened (from the config file); a smart pointer, constructed on the fly, which contains a pointer to the options_st symbol table and NULL for the object address, as is appropriate for a random collection of variables; and, lastly, we pass in the default options for the st_read_stream() function. /* read rc (configuration) file */ rc_file=fopen(“./userchange.rc”,”r”); if(rc_file) { st_read_stream(rc_file, st_smart_pointer(options_st, NULL), st_read_stream_defaults); fclose(rc_file); } Now we will parse the command-line arguments using the same options_st symbol table we used for reading the configuration file. The function st_parse_args() does all the work. We pass a smart pointer with a pointer to the table and no additional address information (NULL), just as we did in the preceding code. And we pass argc and argv, the arguments passed to main() by the C runtime initialization module (“crt0” or equiva- lent). argc is a count of how many arguments are being passed and argv is an array of pointers to character strings, each of which is a single argument passed on the command line. The name of the program is passed as the first argument, argv[0], so don’t be sur- prised if argc is one greater than you expected. /* parse command line arguments */ st_parse_args( st_smart_pointer(options_st, NULL), argc, argv); If you want to see the values of the options after initialization, reading the config file, and parsing arguments, just pass the argument show_args=1, which will trigger the next block of code. st_show() is one of the most commonly used functions. We do not need any special function options right now, so we just use the defaults /* show all the arguments, if appropriate */ if(show_args) { st_show( stdout, st_smart_pointer(options_st, NULL), &st_show_defaults); } A Symbol Table Library A PPENDIX A 759 A A SYMBOL TABLE LIBRARY 4772316072 App A 7/26/99 2:15 PM Page 759 If the program was invoked with the option read_stdin=1, that will trigger this next block of code to read additional options from stdin. This is typically used when a sec- ond slave copy of the program is being run on a remote machine. It might also be used if the program was being driven by a cgi-bin or GUI frontend. The st_read_stream() function is conceptually the exact opposite of st_show() and there is a direct correspondence between the arguments. /* read options from stdin, if appropriate */ if(read_stdin) { st_read_stream(stdin, st_smart_pointer(options_st, NULL), st_read_stream_defaults); } At this point, we have used all the symbol table library functions we need for this pro- gram. We will use them in slightly different ways below as we do application-specific things. The first test is to see if hostname has been set, and if so, we will invoke a remote slave. /* Test if local operation is desired or if we should */ /* forward request to another machine*/ if(strlen(hostname)>0) { The remote_command variable should contain a command that will invoke a remote pro- gram; the substring %s will be used to substitute the name in using snprintf(). snprintf() is like printf() except it prints to a string and, unlike its more common cousin sprintf(), allows you to pass in the size to protect against overflows. In this case, we use remote_command as the format control string. /* remote operation */ fprintf(stderr,”*** REMOTE OPERATION***\n”); snprintf(command, sizeof(command), remote_command, hostname); If the remote slave is invoked with a hostname it would attempt to execute another copy of itself. This would happen again and again. Reliably detecting if the hostname matches the current host is a bit of a nuisance, since a typical networked host has at least three names and may have more if it has multiple network interfaces, virtual hosts, or aliases (DNS CNAME records). If your machine is named “gonzo.muppets.com” then the names “gonzo.muppets.com,”“gonzo,” and “localhost” all refer to the local host. Since we don’t need the hostname anymore, we will take the simple expedient of clobbering the hostname. /* quick kluge to make remote end consider it */ /* to be a local update */ hostname[0]=0; Linux Programming U NLEASHED 760 4772316072 App A 7/26/99 2:15 PM Page 760 Here will we use the popen() command to run the command with the stream pipe piped to its standard input. The command itself will probably invoke a remote copy of changeuser with the stdin and stdout streams forwarded across the network connec- tion. In this case, it is sufficient to only have stdin connected to a pipe; stdout will sim- ply be inherited. If we needed to parse the responses, we would need pipes for both stdin and stdout, which would be more than popen() can handle; in that case, we would need to use pipe(), fork(), either system() or exec(), and a bunch of glue code. We would also need to be careful to avoid a deadlock where both programs were waiting for input from each other, or one program could not write more output until the other program read the output from the first, but the second program was waiting for the first program to read its output. pipe=popen(command, “w”); assert(pipe); Now we will use st_show to dump the options to the pipe we just created. We will termi- nate that output using a line which reads END; if we just closed the pipe to produce an end of file condition, the slave program might be terminated before it had a chance to perform the operation and generate a response. st_show(pipe, st_smart_pointer(options_st, NULL), &st_show_defaults); fprintf(pipe,”END\n”); /* we don’t process output of child at all here */ /* the childs output will end up on stdout */ Now we need to close the pipe, which will have the side effect of waiting for the child process to finish. /* wait for child to exit */ pclose(pipe); The remainder of the program is used for local operation (or the slave in a master-slave relationship). } else { /* local operation */ The function pw_update(), which is not included in the listings for this chapter, reads the passwd file and, optionally, writes a new copy with modifications. It take four parame- ters. The first is a pointer to an error structure that will be updated with the results of the operation. The second parameter is a pointer to a passwd structure that contains values for all of the fields; this may be modified if we are retrieving information. The third is a string giving the name of the file to operate on. The fourth is a string that specifies the A Symbol Table Library A PPENDIX A 761 A A SYMBOL TABLE LIBRARY 4772316072 App A 7/26/99 2:15 PM Page 761 operation to be performed; this may have the values view, add, change, or modify. We invoke the function once with the operation specified by the user and a second time just to read back the data for verification. pw_update(&error, &passwd, passwd_file, operation); pw_update(&error, &passwd, passwd_file, “view”); Now we are going to output a response message for the user or program that invoked userchange. This will begin with the line RESPONSE followed by the error structure, indented 3 spaces and prefixed with the name of the structure. Then we will output a line which reads DATA, followed by the passwd structure, containing the values of all the fields of the passwd file, indented 3 spaces. Finally, we will output a line which reads END to terminate the response. We set the indentation level or other prefix by changing the value of prefix in the func- tion options we pass to st_show(). As mentioned previously, we will initialize the options properly by copying a default option structure. st_show() will be invoked twice and we will modify and reuse the function options structure, st_show_options, each time. /* set indentation level */ st_show_options = st_show_defaults; fprintf(stdout, “RESPONSE\n”); strncpy(st_show_options.prefix, “ error.”,sizeof(st_show_options)); st_show(stdout, st_smart_pointer(error_t_st, &error), &st_show_options); fprintf(stdout, “DATA\n”); strncpy(st_show_options.prefix,” “, sizeof(st_show_options)); st_show(stdout, st_smart_pointer(passwd_t_st, &passwd), &st_show_options); fprintf(stdout, “END\n”); } exit(0); } Linux Programming U NLEASHED 762 4772316072 App A 7/26/99 2:15 PM Page 762 Sample Execution The code fragment below shows sample commands to test execution of userchange after setting up a suitable environment. First, we create a blank password file (do not do this in the real /etc directory). Then we initialize the configuration file, userchange.rc,to val- ues suitable for testing; the blank dummy password file will be used instead of the real one and the program will just call another copy of itself on the same machine instead of trying to invoke a copy of itself on a remote system. Finally, we use the userchange pro- gram to create a user named root with an encrypted password, a user id of 0, a group id of 0, a comment (gecos) field value of root, a home directory of /root, and the shell /bin/bash. rm passwd touch passwd echo ‘passwd_file=”./passwd”’ >userchange.rc echo ‘remote_command=”./userchange read_stdin=1” >>userchange.rc ./userchange operation=add username=root pwcrypt=WwXxYyZz uid=0 gid=0 ➥gecos=”root” homedir=/root shell=/bin/bash The symbol table library simplifies certain forms of user interaction, reading and writing configuration and other data files, and communications with other processes. As the library is enhanced, there may be a few changes that break existing programs in minor ways; if you will be distributing your programs you might want to bind to a specific version of the shared library (that is, link to libsymtab.so.0.55 instead of merely libsymtab.so). A Symbol Table Library A PPENDIX A 763 A A SYMBOL TABLE LIBRARY 4772316072 App A 7/26/99 2:15 PM Page 763 764 4772316072 App A 7/26/99 2:15 PM Page 764 B APPENDIX GNU GENERAL PUBLIC LICENSE 4872316072 App B 7/26/99 2:40 PM Page 765 Version 2, June 1991 Copyright © 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software—to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation’s software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain respon- sibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author’s protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors’ reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone’s free use or not licensed at all. Linux Programming U NLEASHED 766 4872316072 App B 7/26/99 2:40 PM Page 766 The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The “Program”, below, refers to any such program or work, and a “work based on the Program” means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is includ- ed without limitation in the term “modification”.) Each licensee is addressed as “you”. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part con- tains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy GNU General Public License A PPENDIX B 767 B GNU GENERAL PUBLIC LICENSE 4872316072 App B 7/26/99 2:40 PM Page 767 [...]... (asterisk), 610 $ (dollar sign) $< variable, 59 $? variable, 59 $@ variable, 59 $^ variable, 59 $(@D) variable, 59 $(F) variable, 59 $Author$ keyword, 109 $Date$ keyword, 109 $EF_ALIGNMENT variable, 263 $Header$ keyword, 109 $Id$ keyword, 107 -108 $Locker$ keyword, 109 $Log$ keyword, 108 $Name$ keyword, 109 $RCSfile$ keyword, 109 $Revision$ keyword, 109 $Source$ keyword, 109 $State$ keyword, 109 # (hash... 772 Linux Programming UNLEASHED This method was working well—until someone combined the Linux kernel with the GNU system (which still lacked a kernel), and called the combination a Linux system.” The Linux kernel is a free UNIX-compatible kernel written by Linus Torvalds It was not written specifically for the GNU project, but the Linux kernel and the GNU system work together well In fact, adding Linux. .. explicit rules, 56-60 implicit rules, 60-61 makefiles, 54-56 pattern rules, 61 targets, 56-57, 63-64 mknod, 273 moc, 544, 550, 554 nm, 343-344 patch, 98 -100 RCS (Revision Control System) ci, 105 -107 co, 105 -107 ident, 109 - 110 rcs, 114 rcsclean, 113 rcsdiff, 110- 113 rcsmerge, 114 rlog, 113 rpm, 719 sdiff, 98 security, 641-642 tar, 708 trap, 635-637 xemacs, 117 comments Emacs, 126-127 makefiles, 61 communication... root symbolic link, 221 rtc, 224 scsi subdirectory, 226 stat, 218-220, 224 statm, 221 status, 220 sys subdirectory, 226-227 uptime, 224 version, 225 RCS (Revision Control System), 104 -105 checking in/out, 105 -107 comparing, 110- 113 merging, 114 reading fread function, 164 fwrite function, 164 Java, 566-569 read function, 140 renaming, 171 saving, 123 spec build sections, 715 clean sections, 716 example,... application, 441 newterm.c application, 442 noecho.c, 418-419 non-ANSI/ISO source code, 45-46 orbits.c application, 604-606 pu-install.sh, 712 RCS (Revision Control System) howdy.c example, 106 ident command, 109 - 110 $Log$ keyword, 108 sample.el (Emacs), 133 select function, 146-149 semaphore.c program, 293 Server.hxx, 335 errtest.c, 350-351 liberr.c, 348-349 liberr.h, 347 program options symbol table, 751-753... should spread the word that Linux systems” are variant GNU systems—that users of these systems are GNU users, and that they ought to consider the GNU philosophy which brought these systems into existence This article is one way of doing that Another way is to use the terms Linux- based GNU system” (or “GNU /Linux system” or “Lignux” for short) to refer to the combination of the Linux kernel and the GNU... methods, 579 ChatEngine function, 579 checking in/out files (RBS), 105 -107 child library program (process control example), 191-192 child.c file, 194-204 child.h file, 192-194 child_demo1.c demonstration, 204-207 child_demo2.c demonstration, 207-213 child_demo3.c demonstration, 213-214 chroot() environments, 672 ci command (RCS), 105 -107 Clark, James, 529 class keyword, 562 779 4972316072 Index 7/26/99...4872316072 App B 7/26/99 2:40 PM Page 768 768 Linux Programming UNLEASHED of this License (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)... 225 Artistic License, 738 AS variable (makefiles), 59 ASFLAGS variable (makefiles), 60 assert function, 181, 230-232 asterisk (*), 610 AT motherboards, 15 atexit function, 181, 236-237 Athena widgets, 480 C++ class library, 508- 510 Button class, 514-515 Component class, 510- 511 Label class, 513-514 PanedWindow class, 511-513 Text class, 515-517 C++ programs, 507-508 Command Button, 482-484 custom widgets,... UNIX-compatible operating system available for use But ironically, the practice of calling it a Linux system” undermines our method of communicating the GNU idea At first impression, a Linux system” sounds like something completely distinct from the “GNU system.” And that is what most users think it is Most introductions to the Linux system” acknowledge the role played by the GNU software components But they don’t . keyword, 109 $Date$ keyword, 109 $EF_ALIGNMENT variable, 263 $Header$ keyword, 109 $Id$ keyword, 107 -108 $Locker$ keyword, 109 $Log$ keyword, 108 $Name$ keyword, 109 $RCSfile$ keyword, 109 $Revision$. 109 $RCSfile$ keyword, 109 $Revision$ keyword, 109 $Source$ keyword, 109 $State$ keyword, 109 # (hash sign), 61 % (percent sign), 61 ? (question mark), 610 3D graphics Mesa, 596 OpenGL, 596-597. See also. software. Linux Programming U NLEASHED 772 4872316072 App B 7/26/99 2:40 PM Page 772 We should not accept the splitting of the community in two. Instead we should spread the word that Linux systems”