4 @PageFooting(center "Draft of @value(date)")
5 @style(spacing = 1.5, indent 5, FontFamily = TimesRoman, size = 12)
6 @style(LeftMargin 1 inch, RightMargin 1 inch)
10 @b[The Athena Service Management System]
11 @blankspace ( 1 line )
12 @b[SMS Client Internals Document]
13 @blankspace ( 1 line )
16 @CopyrightNotice(Massachusetts Institute of Technology)
19 @Chapter(Introduction)
21 The @i(Sms Client) program was designed to allow ordinary users a
22 simple method of performing all database manipulations common here at
23 @i(Project Athena). The user interacts with the program through a
24 terminal based menu. This allows use of sms on a wide variety of
25 platforms. Unlike previous packages where many different clients were
26 necessary to perform all these tasks, the @i(Sms Client) program
27 allows all operations to be performed from one application. This
28 saves the user time and effort by having all common operations in one
29 convenient place. I have spent a good deal of time cleaning up the
30 code to make it uniform throughout the entire client and am writing
31 this document to explain some of the decisions. My hope is that this
32 will allow you to add features with a minimum of amount effort, as
33 well as easing the transition between your code and mine.
37 This section presents general concepts that hold throughout the code.
38 Some of the items may seem trivial, but together they keep the code
39 consistent and understandable.
41 @Section(File Organization)
43 Most files correspond to one type of item in the @i(SMS) database,
44 such as lists, machines, clusters, etc. These files are self
45 contained so that you can pick and choose which of these you would
46 like to use in any new client you decide to build. There are a few
47 special files that do not follow this convention.
50 @i[util.c]@\Utility functions used by many of the other files.
52 @i[menu.c]@\Menu definitions for the entire application.
54 @i[main.c]@\The main driver that handles application start up.
56 @i[delete.c]@\Functions that handle deletion of lists and users.
58 @i[globals.c]@\All global variable definitions.
61 @Section(Command Organization)
63 Each menu item has one and only one function associated with it,
64 although the same function may be used by two identical menu items.
65 The arguments passed to these functions from the menu package are an
66 array of character strings and the number of strings in the array.
67 The first argument in the array (argv[0]) is the name of the menu item
68 that has been selected. Thus the actual user specified arguments are
69 passed starting at the second argument (argv[1]).
71 @Section(Naming and Comment Conventions)
76 I use all capital letters for constants, while variables are all small
77 letters, and functions are represented by mixing capital and small
78 letters, capitalizing each word in the function name. I use long
79 function names as functions are usually not called often, and long
80 names are much more descriptive. There are a few functions that do
81 not follow the mixed caps and small convention, these are generally
82 those I called out of @i(SMSLib), @i[CLib], or the menu package.
86 Each file has a header containing the Revision Control System (RCS)
87 modification time and some history information, as well as some
88 information about the file. The template for this is a file named
89 'header'. Each function has a comment preceding it describing the
90 function, all variables used, and the value that this function
91 returns. Notes of special concern for this function are also listed
92 here. The function template is in a file called, surprisingly enough,
93 'function'. Other comments are placed where appropriate.
95 @Section(Retrieving data from the server)
98 Since one of the limitations of @i[SMS] is that no query may be
99 executed recursively, all information returned by a query must be
100 received before another query can be executed. To facilitate
101 programming simplicity I store the information returned from each
102 query into a queue as soon as it is received. This allows a simple,
103 although rather memory intensive, method of getting around this
104 problem. Another advantage of this method is that since no operations
105 are taking place on the data as it comes back from the server the time
106 that the server spends sending the data to the clients is kept to a
107 minimum, a necessity in large-scale environments.
109 @Chapter[Application Wide Definitions]
111 This section will cover all items that cross function boundaries,
112 including global variables, structure definitions, and constant
115 @Section[Global Variables]
117 @Label(Globals)The @i[SMS Client] has a few global variables. Since
118 you will run into them throughout the application they warrant mention
125 @i[program_name] @\This is the name of the program currently being
126 executed, and is retrieved from argv[0] in @i[main.c].
128 @i[user] @\This is the name of the user currently executing the program,
129 and is also set in @i[main.c].
131 @i[verbose] @\This is a boolean value that, when FALSE turns off the
132 delete confirmation. For more information see section @ref(confirm).
134 @i[found_some] @\This is a boolean that allows the @b[PrintByType()]
135 (sect. @ref(pbytype) function to be able to communicate with the
136 function calling the query that invokes it, as well as among calls to
140 @Section[Structure Definitions]
144 The only global structure definition is the one for the queue element.
145 What I will refer to as the queue is actually a doubly linked list
146 that all my queue manipulation functions (sect. @ref(queuecount))
147 treat as a true queue.
151 struct qelem *q_forw;
152 struct qelem *q_back;
157 The queue data need not be a string; @i[char *] is used as a generic
160 @Section[Definitions]
166 For readability there are a few important global definitions.
167 Function pointers in @i[C] tend to be tough to read so I have typedef'ed the
168 function pointers; FVoid, FInt, and FCharStar. These refer to functions
169 that return nothing, integers, and strings, respectively.
173 Another global definition, MOD_FORMAT, is used to format the
174 modification information of an item for printing. It is important that
175 all modification information is presented to the user with this
176 format, to keep the @i[SMS Client] consistent.
181 Information about an item in the database is returned by sms_query()
182 in an array of strings. Remembering what @i[info][7] is can be
183 difficult and it is possible that in future updates of the @i[SMS
184 Server] @i[info][7] may contain completely different information. To
185 solve both of these problems I have created a set of definitions for
186 each element of the argument list of each data type that the @i[SMS
187 Client] uses. A list of these can be found in appendix
188 @ref(a_infodefs), as well as the file @i[infodefs.h].
190 @Chapter(Utility Functions)
192 I created several utility functions that handle common operations used
193 by many of the functions in the @i[SMS Client]. These functions
194 perform things like the storing of information in a queue as it comes
195 in from the @i(SMS Server), queue manipulation, querying the user,
196 and printing information.
198 @Section(Storing and Freeing the Queue)
200 As noted in section @ref(queue-def), all incoming information from the
201 @i(SMS Server) is stored in a queue as soon as it is received. The
202 function that does this, @b[StoreInfo()], as well the one that frees the
203 queue when we are finished with it, @b[FreeQueue()], are described here.
207 Use the function @b[StoreInfo()] to store all information received
208 from the @i[SMS Server] into a queue. Space for this queue is
209 dynamically allocated using malloc(). The actual information is
210 stored in a NULL terminated array of strings. The number of strings
211 in this array can be easily found with the function @b[CountArgs()]
212 (sect. @ref(countargs)).
216 StoreInfo(@i[argc, argv, data])
223 @i[argc] @\The number of strings passed in argv.
225 @i[argv] @\An array of strings to be stored in the queue.
227 @i[data] @\A pointer to the previous element in this queue, or NULL if@\it
228 should create a new queue. This is updated with each call to @b[StoreInfo()]
229 and the value associated with this pointer is the last element in the
234 Here is an example of an @i[SMS] query that would use this function to store
239 struct qelem * elem = NULL;
240 status = sms_query("query handle", num_args, args, StoreInfo, &elem);
244 The variable elem must initially be set to NULL, or @b[StoreInfo()]
245 will try to add the first element of this queue to a currently
246 existing queue that is really just the garbage left on the stack. The
247 value of elem when this query returns is the last element in the
248 queue, and the function @b[QueueTop()] (section @ref(queuetop)) should
249 be used to get the top element of the queue, which is expected by most
250 other queue operations.
256 To free the queue and any data associated with it, the function
257 @b[FreeQueue()] is used. This function expects a queue similar to the
258 one created by the @b[StoreInfo()] function. @b[FreeQueue()] frees
259 all memory associated with this particular queue, and will do bad
260 things if the information stored in the queue is not a NULL
261 terminated, allocated array of allocated strings. All allocations
262 are assumed to have been done with the @i[C] malloc() function.
268 struct qelem * @i[elem];
272 @i[elem] @\Any element in the queue. The entire queue will be freed
273 regardless of the element passed.
276 @Section[Queue Manipulation]
278 The following group of functions perform common tasks that involve
279 retrieving information from or manipulating a queue. All these functions
280 will handle NULL passed to them in an appropriate manner, either returning
286 To find the top element of a queue use the function @b[QueueTop()].
292 struct qelem * @i[elem];
295 @i[elem] @\Any element in the queue.
300 @b[QueueTop()] returns the top element of the queue defined by its
309 The function @b[QueueCount()] counts the number of elements in a queue.
314 struct qelem * @i[elem];
317 @i[elem] @\Any element in the queue.
322 @b[QueueCount()] returns the number of elements in the queue defined
323 by it argument, it need not be the top element, any
326 @Section[Array Manipulation]
328 The arrays of strings have some manipulation functions of their own.
329 All arrays used in the @i[SMS Client] are assumed to be NULL terminated.
330 In general this is no problem as @b[StoreInfo()] creates NULL terminated
336 @b[CountArgs()] counts the number of elements in a NULL
337 terminated array of strings.
345 info @\A NULL terminated array of character strings.
350 @b[CountArgs()] returns the number of strings in the NULL terminated array
351 of strings passed to it. A common use of @b[CountArgs()] is to tell
352 sms_query() how many items are in the argument list passed to the
353 query, as shown below.
356 status = sms_query("query", CountArgs(args), args, StoreInfo, &elem);
362 To free all elements in a NULL terminated array of strings use the
363 @b[FreeInfo()] function.
373 @i[info] @\A NULL terminated array of strings allocated with malloc(),
381 @Index(SlipInNewName)
383 Most update queries use the same argument list that is returned by the
384 information query for the database item is question. For instance,
385 update_list uses almost the same arguments that get_list_info returns.
386 The difference in these arguments lists is that update queries expect
387 the new name to be the second element in the list. The
388 @b[SlipInNewName()] function adds the new name as the second argument
389 in the list passed to it, bumping all the other arguments down one
394 SlipInNewName(@i[info, name])
400 @i[info] @\A NULL terminated array of strings.
402 @i[name] @\The new name to be slipped into @i[info] at position @i[info][1].
407 Once @b[SlipInNewName()] has been performed on a argument list do not
408 try to use the definitions for that type of element, as they will be
409 wrong. Don't use @i[info][L_ACE] to try to retrieve the ace of the
410 list, as this function has shifted all the items except the old name
413 @Section[Special Queue Functions]
415 The following two functions @b[Loop()] and @b[QueryLoop()] are used
416 when an operation needs to be performed on every element of the queue.
417 The difference between these two functions is that @b[QueryLoop()]
418 presents a method of asking the user if the operation should be
419 performed, while @b[Loop()] just performs it on each element.
424 To perform an operation on every element in the queue use the
429 Loop(@i[top, LoopFunc])
430 struct qelem * @i[top];
434 @i[top] @\The top element of the queue.
436 @i[LoopFunc] @\The function to perform on each element of the queue.
441 The @i[LoopFunc] has the following format and is performed with the
442 data of each element in the queue.
450 @i[info] @\The array of strings that is stored as the @i[q_data] of each element
456 No provision is made for the @i[LoopFunc] function to return a value.
464 @Index(QueryLoopFunc)
466 If you want to query the user before your function is called on each
467 element of the queue, use the @b[QueryLoop()] routine.
471 QueryLoop(@i[top, PrintFunc, QueryLoopFunc, query_string])
472 struct qelem * @i[top];
473 FCharStar @i[PrintFunc];
474 FVoid @i[QueryLoopFunc];
475 char * @i[query_string];
478 @i[top] @\The top element of the queue.
480 @i[PrintFunc] @\The function that will print information to the user
481 about each specific element of the queue, its return value is appended
482 to the query string, and asked as a @b[YesNoQuitQuestion()] (sect.
483 @ref[ynqquestion]) of the user.
485 @i[QueryLoopFunc] @\This function is called if the user answers yes to the
486 question asked of him, or if there is only one element in the queue.
488 query_string @\Basic prompt for the @b[YesNoQuitQuestion()] asked of
489 the user, the string returned by the @i[PrintFunc] is appended to this
490 string to form the full prompt.
497 @i[PrintFunc] is called using the data stored in each element of the
498 queue, unless there is only one element in the queue, in which case
499 @i[QueryLoopFunc] is called without querying the user. @i[PrintFunc]
500 has the following format.
509 @i[info] @\The array of strings that is stored as the @i[q_data] of
510 each element in the queue.
515 The @i[PrintFunc] returns a string that is to be appended to the
516 query_string() of the @b[QueryLoop()] function. This string is then
517 used to ask the user if the @i[QueryLoopFunc] should be called. The
518 return string from the @i[PrintFunc] is usually just the name of the
519 item contained in the data field of each queue element.
521 @Index(QueryLoopFunc)
523 @i[QueryLoopFunc] is called each time the user answers 'yes' to the
524 question asked of him, with the current element's information. The
525 only exception to this is if the queue has only one element, in which
526 case @i[QueryLoopFunc] is called immediately with @i[one_item] set to TRUE.
527 @i[QueryLoopFunc] has this format.
531 QueryLoopFunc(@i[info, one_item])
537 @i[info] @\The array of strings that is stored as the @i[q_data] of
538 each element in the queue.
540 @i[one_item] @\This is TRUE if this function is being called without asking
541 the user, because there is only one item in the queue.
546 No provision is made for the @b[QueryLoop()] function to return a value.
548 @b[QueryLoop()] automatically performs the @i[QueryLoopFunc] without
549 calling the @i[PrintFunc] if there is only one item in the queue, but
550 the @i[QueryLoopFunc] is alerted to this fact by the @i[one_item]
551 variable. If there is more than one item on the queue the the
552 @i[PrintFunc] is executed, and the user is prompted, as in the
560 QueryLoop(top_of_queue, PrintListInfo, UpdateList, "Would you like to update list");
566 List: foo @\Members: @\35
567 This list is a group@\GID: @\9803
569 Would you like to update list foo (y/n/q) [n]:
572 This question is asked of the user for every item in the queue, and if
573 the answer is yes then the @i[QueryLoopFunc] is called. If the answer
574 is no then it continues onto the next element, quit drops out of the
579 The return value of the @i[PrintFunc] is the name of the list in the
580 above example (i.e. foo). A simple print function, @b[Nullprint()],
581 is detailed in section @ref(nullprint). If @b[Nullprint()] were used
582 in the above example following would be the result:
587 Would you like to update list foo (y/n/q) [n]:
590 @Section[Generic @i{SMS} query routines]
592 These two very common routines are used as sms_query() callbacks.
593 Using these common routines helps other programmers immediately
594 identify what type of tuples your query is expected to return.
598 Use the @b[Scream()] function when you do not expect any tuples to be
599 returned by the @i[SMS Server], as in an update, add, or delete query.
606 A Sample use of this function.
609 status = sms_query("update_list", CountArgs(args), args, Scream, NULL);
617 @b[NullFunc()] does nothing at all with the tuples, it just ignores them.
624 @b[NullFunc()] is useful when you are expecting tuples to be returned,
625 but are not interested in their contents, I used it when I was testing
626 for existence of a list by performing a count_members_of_list query
627 and then testing the return value, but was not interested in the
628 tuples. A sample use of this @b[NullFunc()].
631 status = sms_query("get_list_info", CountArgs(args), args, NullFunc, NULL);
634 @Section[Retrieving User Input]
636 To keep a consistent user interface across the entire application, the
637 @i[SMS Client] uses the following functions to handle most user input.
638 The only other accepted method of retrieving user input is by making
639 a call to @b[Prompt_input()], which is in the menu library, and the
640 basis for all these functions.
642 @Index(PromptWithDefault)
644 Use @b[PromptWithDefault()] when you need to prompt the user for a value
645 and you want to provide him with a default value.
649 PromptWithDefault(@i[prompt, buf, buflen, def])
650 char * @i[prompt], * @i[buf];
656 prompt @\The string to prompt the user with.
658 buf @\The buffer to return the answer in.
660 buflen @\The length of the return buffer.
662 def @\The default return value (if NULL then "" is the default).
668 A typical call to this function is as follows:
673 PromptWithDefault("Input a value for the string", buf, BUFSIZ, "foo");
677 Input a value for the string [foo]:
681 @b[PromptWithDefault()] will return (-1) if the user breaks out of this
682 prompt with control-C or some other break character.
688 @Index(YesNoQuestion)
690 @b[YesNoQuestion()] is used to ask the user a question that is best
691 answered with a response of either yes or no. It also gives the user
692 a default value in the same form as @b[PromptWithDefault()].
696 YesNoQuestion(@i[prompt, bool_def])
702 @i[prompt] @\The string to prompt the user with.
704 @i[bool_def] @\The default value, either TRUE or FALSE.
709 @b[YesNoQuestion()] returns either TRUE or FALSE, or possibly (-1) on
710 a break by the user. The only accepted values from the user are 'y',
711 'Y', 'n', and 'N'. All other values prompt the user with "Please
712 answer 'y' or 'n'." and ask the question again.
718 @Index(YesNoQuitQuestion)
720 Use @b[YesNoQuitQuestion()] when you want the user to have the option to
721 quit as well as answer yes or no.
725 YesNoQuitQuestion(@i[prompt, bool_def])
732 @i[prompt] @\The string to prompt the user with.
734 @i[bool_def] @\The default value, either TRUE or FALSE.
739 @b[YesNoQuitQuestion()] is very similar to @b[YesNoQuestion()], in
740 fact the only difference is that this function interprets the keys 'q'
741 and 'Q' the same as hitting a break, causing
742 @b[YesNoQuitQuestion()] to return (-1).
750 When you want to ask the user for delete confirmation use the @b[Confirm()]
759 @i[prompt] @\The string to prompt the user with.
764 @b[Confirm()] is a specialized user input function. This function is
765 meant to be used only when making delete confirmation. It will
766 immediately return TRUE if the verbose global variable (see section
767 @ref(globals)) is FALSE, implying that no confirmation is wanted.
768 Otherwise it asks the user a @b[YesNoQuestion()] using its argument as
769 the prompt, with a default value of FALSE. If the user answers yes
770 then the function will return TRUE, otherwise FALSE is returned.
776 @Index(GetValueFromUser)
778 The @b[GetValueFromUser()] routine is used to update a string that was
779 previously allocated with malloc().
783 GetValueFromUser(@i[prompt, pointer])
784 char * @i[prompt], ** pointer;
787 @i[prompt] @\The string to prompt the user with.
789 @i[pointer] @\A pointer to the malloced item that is to be updated, or a
793 @Blankspace( 1 line )
795 @b[GetValueFromUser()] returns SUB_ERROR if the user broke out of the
796 prompt with control-C, else SUB_NORMAL. The old value is freed,
797 unless it is NULL, and the new value is allocated and pointed to by
803 @Index(GetYesNoValueFromUser)
805 If the value to be updated is an @i[SMS] style boolean ("0" or "1")
806 then use the the @b[GetYesNoValueFromUser()] function, which asks the
807 user a @b[YesNoQuestion()].
811 GetYesNoValueFromUser(@i[prompt, pointer])
812 char * @i[prompt], ** @i[pointer];
816 @i[prompt] @\The string to prompt the user with.
818 @i[pointer] @\A pointer to the malloced item that is to be updated, or a
824 @b[GetYesNoValueFromUser()] also returns SUB_ERROR if the user broke
825 out of the prompt with control-C, and SUB_NORMAL otherwise.
826 @i[pointer] is freed - Unless it is NULL - and reset to point to a
827 properly allocated value of "0" or "1" depending upon the user's answer
835 The @i[SMS Server] expects file types to be passed as an integer bit
836 mask. Use the @b[GetFSTypes()] function to query the user about the
837 new value of this field.
841 GetFSTypes(@i[pointer])
846 @i[pointer] @\A pointer to the current allocated filesystem type that
847 is to be updated, or a pointer to NULL.
852 @b[GetFSTypes()] returns SUB_ERROR if the user broke out of the prompt
853 with control-C, and SUB_NORMAL otherwise. It also constructs the
854 correct bit field by asking the user about each type, providing a
855 default value, of course. The new filesystem type is passed back as
856 the new value pointed to by @i[pointer]. If non-NULL the old pointer
859 @Section[Printing Routines]
861 Here are a few general printing routines. Most printing is done with
862 routines that are specific to the type of database item we are dealing
863 with, but these few printing functions are general enough to describe
869 Use the @b[Print()] function to print out all elements in each tuple
870 returned by a call to sms_query().
874 Print(@i[argc, argv, callback]);
876 char ** @i[argv], * @i[callback];
880 @i[argc] @\The number if strings passed in argv.
882 @i[argv] @\An array of strings that is the data to be stored in the queue.
884 @i[callback] @\Not Used.
889 @b[Print()] returns SMS_CONT. Every time this function is called it
890 sets the global variable @i[found_some] to TRUE.
897 If you want something a bit more specialized then try
898 @b[PrintByType()]. If a string compare of @i[argv][0] and
899 @i[callback] shows them to be equal then the tuple is printed. If
900 @i[callback] is NULL then it acts exactly like @b[Print()].
904 PrintByType(@i[argc, argv, callback]);
906 char ** @i[argv], * @i[callback];
910 @i[argc] @\The number if strings passed in argv.
912 @i[argv] @\An array of strings that is the data to be stored in the queue.
914 @i[callback] @\@i[Argv][0] is compared to this with strcmp() and if
915 they are equal then the tuple printed. In the special case where
916 callback is NULL all tuples are printed.
921 @b[PrintByType()] returns SMS_CONT. Every time this function is
922 called it sets the global variable found_some to TRUE.
929 If the help information is stored in a NULL terminated array of strings
930 then use the @b[PrintHelp()] function to print the information for the user.
934 PrintHelp(@i[message])
939 @i[message] @\The help message stored in a NULL terminated array of strings.
944 @b[PrintHelp()] returns DM_NORMAL to allow help routines to remain as
953 When using the @b[QueryLoop()] function (sect. @ref(qloop)) there are
954 times when all the @i[PrintFunc] needs to return is the name of the item, if
955 the item's name is the first element of the tuple then use the @b[NullPrint()]
956 function to retrieve this name.
964 info@\ An array of strings.
969 @b[NullPrint()] returns the first element in the array passed to it,
972 @Section[Miscellaneous Utility Functions]
974 This section contains the rest of the utility functions, these don't
975 really fit into a category.
979 Use @b[FreeAndClear()] to free a pointer and set it to NULL.
983 FreeAndClear(@i[pointer, free_it])
990 @i[pointer] @\A pointer to the item to free or clear, if this item is
991 NULL then the function does not try to free it.
993 @i[free_it] @\This function always sets the item to NULL, but only if
994 this is TRUE is it freed.
1004 @b[ValidName()] check to see if string is a valid name for a new
1005 item in the database.
1014 @i[s] @\The string to check.
1017 @Blankspace( 1 line )
1019 If the name is not valid, @b[ValidName()] alerts the user to the
1020 problems encountered and returns FALSE. Checks are made to see if
1021 this name contains a wildcard, contains spaces, or has no characters
1022 at all. This is by no means an exhaustive search, but does handle some
1023 common things that confuse the database.
1028 @Index(ToggelVerboseMode)
1030 The @b[ToggleVerboseMode()] function is associated with the menu items
1031 that allows the user to toggle the verbose global variable (see sect.
1039 Use the @b[Strsave()] function to allocate space for a new string.
1048 @i[str] @\The string that needs to have space allocated for it.
1051 @Blankspace( 1 line )
1053 @b[Strsave()] returns an allocated copy of the string passed to it.
1058 @Index(EncryptMITID)
1059 @Index(RemoveHyphens)
1061 To save an MIT ID number two functions are needed, @b[EncryptMITID()] and
1062 @b[RemoveHyphens()].
1066 EncryptMITID(@i[sbuf], @i[idnumber], @i[first], @i[last])
1067 char * @i[sbuf], * @i[idnumber], * @i[first], * @i[last];
1071 @i[spbuf] @\The buffer used to return the encrypted id number.
1073 @i[idnumber] @\The unencrypted id number.
1075 @i[first, last] @\The name of the user whose id number we are encrypting.
1085 RemoveHyphens(@i[str)]
1091 @i[str] @\This is the string with hyphens to remove, when the function
1092 returns it will no longer have hyphens.
1095 @Chapter[Function Organization within Files]
1097 The functions within each of the files tend to be quite similar. I
1098 have organized these so that at the top of the file are all the
1099 general routines for the type of element currently being worked upon.
1100 In @i[attach.c], for example, there is a @b[PrintFSInfo()] function, an
1101 @b[AskFSInfo()] function, and a @b[GetFSInfo()] function. Each of the
1102 item types will have a file that contains very similar functions, and
1103 all will be grouped near the top of the file. As an example consider the
1104 general functions in @i[attach.c].
1106 @b[PrintFSInfo()] is used to print out all the information about a filesystem.
1110 PrintFSInfo(@i[info])
1115 @i[info] @\A NULL terminated array of strings that contains all information
1121 @b[PrintFSInfo()] has the same format as @i[PrintFunc] (sect.
1122 @ref(qloop)) and can be used as the @i[PrintFunc] for @b[QueryLoop()]
1123 calls in the functions that update and delete filesystems.
1128 @b[AskFSInfo()] is used to ask the user to update the current filesystem
1133 AskFSInfo(@i[info, name])
1140 @i[info] @\A NULL terminated array of malloced strings that contains
1141 all information about a filesystem. When the function is called this
1142 array contains the default values to present to the user, and when the
1143 function is returned this array contains the argument list for the
1144 update or add query.
1146 @i[name] @\A boolean value that when TRUE tells this function to ask
1147 the user for a new value for the name of this filesystem, and then
1148 slip it into the @i[info] list, using @b[SlipInNewName()] (sect.
1152 @Blankspace( 1 line )
1154 The return value of @b[AskFSInfo()] is just the @i[info] array after
1155 it has been updated with the new values. This function is used to
1156 perform most of the information gathering in the update and add
1157 filesystem queries. For an update query the information returned from
1158 a @i[get_filesys_by_label] can be used for the @i[info] array, but for
1159 an add filesystem, the program must come up with a reasonable set
1160 default values for the @i[info] array.
1162 If the @i[name] flag is set then the @b[SlipInNewName()] function is
1163 called to add a new name to the @i[info] array, this causes the array
1164 indices for most values to be changed and thus the predefined values
1165 used to access the information in this array can no longer be used
1166 (see sections @ref(infodefs) and @Ref(sinn)).
1171 The @b[GetFSInfo()] function is used to to perform common information
1172 gathering @i[SMS] queries for a filesystem.
1175 static struct qelem *
1176 GetFSInfo(@i[type, name])
1182 @i[type] @\The type of filesystem query to make, can be one of;
1183 LABEL, MACHINE, GROUP or ALIAS. The valid names for @i[type] are
1184 typedef'ed at the beginning of each file.
1186 @i[name] @\The name to pass as the argument to the query.
1191 The @b[GetFSInfo()] function is a simple method of making the most
1192 common information gathering @i[SMS] queries, it handles all return
1193 values from the call to sms_query() and returns the top element of a
1194 queue containing all information returned by the server. If an error
1195 is detected then NULL is returned and an error message is printed to
1198 After this group of general functions come those that actually
1199 correspond to items in the menu. These commonly perform get, add,
1200 update, and delete operations. For more information on the functions
1201 in each of the files see the appendix @ref(fqlist).
1203 @Appendix(The @i[SMS] Query String Array Definitions)
1210 * This file contains all definitions that allow easy access to
1211 * elements returned by most of the @i[SMS] queries.
1213 * If the order of the arguments in the @i[SMS] queries change (again)
1214 * then all that needs to be changed are the values of these items
1215 * and all should be well, (hopefully :-).
1217 * Chris D. Peterson - kit@@athena
1226 #include "mit-copyright.h"
1236 /* alias queries. */
1238 #define ALIAS_NAME 0
1239 #define ALIAS_TYPE 1
1240 #define ALIAS_TRANS 2
1243 /* Cluster information queries */
1246 #define C_DESCRIPT 1
1247 #define C_LOCATION 2
1253 /* Cluster Data information queries */
1260 /* Delete Member from list queries. */
1267 /* Filesys queries */
1271 #define FS_MACHINE 2
1273 #define FS_M_POINT 4
1275 #define FS_COMMENTS 6
1279 #define FS_L_TYPE 10
1280 #define FS_MODTIME 11
1282 #define FS_MODWITH 13
1285 /* Get List Of Member queries. */
1288 #define GLOM_ACTIVE 1
1289 #define GLOM_PUBLIC 2
1290 #define GLOM_HIDDEN 3
1291 #define GLOM_MAILLIST 4
1292 #define GLOM_GROUP 5
1295 /* General List information queries. */
1301 #define L_MAILLIST 4
1304 #define L_ACE_TYPE 7
1305 #define L_ACE_NAME 8
1307 #define L_MODTIME 10
1309 #define L_MODWITH 12
1312 /* List Member information queries. */
1319 /* Machine information queries */
1328 /* Machine to cluster Mapping */
1330 #define MAP_MACHINE 0
1331 #define MAP_CLUSTER 1
1334 /* NFS phys. queries. */
1338 #define NFS_DEVICE 2
1339 #define NFS_STATUS 3
1342 #define NFS_MODTIME 6
1344 #define NFS_MODWITH 8
1347 /* PO box information queries */
1359 #define Q_DIRECTORY 3
1366 /* User information queries */
1379 #define U_MODWITH 11
1382 #endif _infodefs_ /* Do not add anything after this line. */
1388 @Appendix(List of Menus, Functions, and Query Names)
1392 @blankspace(2 lines)
1394 The menu tree for the @i[SMS Client] has three levels, the root, tier
1395 1 and tier 2. A diagram of the menu tree is show in appendix @ref(tree).
1396 The root of the tree is composed of calls to other menus.
1398 @blankspace(2 lines)
1401 @Center(Sms Database Manipulation)
1404 1. (cluster) Cluster Menu.
1405 2. (filesys) Filesystem Menu.
1406 3. (list) Lists and Group Menu.
1407 4. (machine) Machine Menu.
1408 5. (nfs) Physical NFS Menu.
1409 6. (user) User Menu.
1410 t. (toggle) Toggle logging on and off.
1415 @Section[First Tier Menus]
1417 @Center{ @b[Cluster Menu] }
1421 1. (show) Get cluster information.
1422 2. (add) Add a new cluster.
1423 3. (update) Update cluster information.
1424 4. (delete) Delete this cluster.
1425 5. (mappings) Machine To Cluster Mappings Menu.
1426 6. (c_data) Cluster Data Menu.
1427 7. (verbose) Toggle Verbosity of Delete.
1428 r. (return) Return to previous menu.
1429 t. (toggle) Toggle logging on and off.
1437 add@\get_cluster@\add_cluster
1438 update@\get_cluster@\update_cluster
1439 delete@\get_cluster@\delete_cluster
1443 @Center{ @b[Filesystem Menu] }
1447 1. (get) Get Filesystem Name Information.
1448 2. (add) Add New Filesystem to Database.
1449 3. (change) Update Filesystem Information.
1450 4. (delete) Delete Filesystem.
1451 5. (check) Check An Association.
1452 6. (alias) Associate with a Filesystem.
1453 7. (unalias) Dissociate from a Filesystem.
1454 8. (quotas) Quota Menu.
1455 9. (verbose) Toggle Verbosity of Delete.
1457 r. (return) Return to previous menu.
1458 t. (toggle) Toggle logging on and off.
1465 get@\get_filesys_by_label
1466 add@\get_filesys_by_label@\add_filesys
1467 change@\get_filesys_by_label@\update_filesys
1468 delete@\get_filesys_by_label@\delete_filesys
1470 alias@\get_alias@\add_alias
1471 unalias@\get_alias@\delete_alias
1475 @Center{ @b[List Menu] }
1479 1. (show) Display information about a list.
1480 2. (add) Create new List.
1481 3. (update) Update characteristics of a list.
1482 4. (delete) Delete a List.
1483 5. (query_remove) Interactively remove an item from all lists.
1484 6. (members) Member Menu - Change/Show Members of a List.
1485 7. (list_info) List Info Menu.
1486 8. (quotas) Quota Menu.
1487 9. (verbose) Toggle Verbosity of Delete.
1488 10. (help) Print Help.
1489 r. (return) Return to previous menu.
1490 t. (toggle) Toggle logging on and off.
1498 add@\get_list_info@\add_list
1499 update@\get_list_info@\update_list
1500 delete@\get_list_info@\get_ace_use
1501 @\count_members_of_list@\get_lists_of_member
1502 @\get_members_of_list@\delete_list
1503 @\delete_member_from_list
1504 query_remove@\get_lists_of_member@\delete_member_from_list
1508 @Center{ @b[Machine Menu] }
1512 1. (show) Get machine information.
1513 2. (add) Add a new machine.
1514 3. (update) Update machine information.
1515 4. (delete) Delete this machine.
1516 5. (mappings) Machine To Cluster Mappings Menu.
1517 6. (verbose) Toggle Verbosity of Delete.
1518 r. (return) Return to previous menu.
1519 t. (toggle) Toggle logging on and off.
1527 add@\get_machine@\add_machine
1528 update@\get_machine@\update_machine
1529 delete@\get_machine@\delete_machine
1533 Delete machine needs to make some other checks. For lack of time these
1534 have not been implemented.
1537 Is the machine a server@\get_server_host_info
1539 Is the machine an NFS server@\get_nfsphys
1541 Are there any ACE's that this machine references@\get_server_host_access
1546 @Center{ @b[NFS Physical Menu] }
1550 1. (show) Show an NFS server.
1551 2. (add) Add NFS server.
1552 3. (update) Update NFS server.
1553 4. (delete) Delete NFS server.
1554 5. (quotas) Quota Menu.
1555 6. (verbose) Toggle Verbosity of Delete.
1556 r. (return) Return to previous menu.
1557 t. (toggle) Toggle logging on and off.
1565 add@\get_nfsphys@\add_nfsphys
1566 update@\get_nfsphys@\update_nfsphys
1567 delete@\get_nfsphys@\get_filesys_by_nfsphys
1572 @Center{ @b[User Menu] }
1576 1. (login) Show user information by login name.
1577 2. (name) Show user information by name.
1578 3. (class) Show names of users in a given class.
1579 4. (modify) Change all user fields.
1580 5. (adduser) Add a new user to the database.
1581 6. (register) Register a user.
1582 7. (delete) Delete user.
1583 8. (udelete) Delete user by uid.
1584 9. (pobox) Post Office Box Menu.
1585 10. (quota) Quota Menu.
1586 11. (verbose) Toggle Verbosity of Delete.
1587 r. (return) Return to previous menu.
1588 t. (toggle) Toggle logging on and off.
1595 login@\get_user_by_login
1596 name@\get_user_by_name
1597 class@\get_user_by_class
1598 modify@\get_user_by_login@\update_user
1600 register@\get_user_by_name@\register_user
1601 @\Kerberos server is queried also.
1602 delete@\delete_user@\get_filesys_by_label
1603 @\delete_filesys@\get_members_of_list
1604 @\delete_list@\count_members_of_list
1605 @\get_lists_of_member@\delete_member_from_list
1606 @\get_list_info@\get_ace_use
1607 udelete@\get_user_by_uid@\(plus all of the above).
1611 @Section[Second Tier Menus]
1613 @Center{ @b[Cluster Data Menu] }
1617 1. (show) Show Data on a given Cluster.
1618 2. (add) Add Data to a given Cluster.
1619 3. (delete) Remove Data to a given Cluster.
1620 4. (verbose) Toggle Verbosity of Delete.
1621 r. (return) Return to previous menu.
1622 t. (toggle) Toggle logging on and off.
1629 show@\get_cluster_data
1630 add@\add_cluster_data
1631 delete@\get_cluster_data@\delete_cluster_data
1635 @Center{ @b[List Information Menu] }
1639 1. (member) Show all lists to which a given member belongs.
1640 2. (admin) Show all items which a given member can administer.
1641 3. (groups) Show all lists which are groups.
1642 4. (public) Show all public mailing lists.
1643 5. (maillists) Show all mailing lists.
1644 r. (return) Return to previous menu.
1645 t. (toggle) Toggle logging on and off.
1652 member@\get_lists_of_member
1654 groups@\qualified_get_lists
1655 public@\qualified_get_lists
1656 maillists@\qualified_get_lists
1660 @Center{ @b[Mappings Menu] }
1664 1. (map) Show Machine to cluster mapping.
1665 2. (addcluster) Add machines to a clusters.
1666 3. (remcluster) Remove machines from clusters.
1667 4. (verbose) Toggle Verbosity of Delete.
1668 r. (return) Return to previous menu.
1669 t. (toggle) Toggle logging on and off.
1676 map@\get_machine_to_cluster_map
1677 addcluster@\get_machine@\get_cluster
1678 @\add_machine_to_cluster
1679 remcluster@\get_machine_to_cluster_map
1680 @\delete_machine_from_cluster
1684 @Center{ @b[Membership Menu] }
1688 1. (add) Add a member to this list.
1689 2. (remove) Remove a member from this list.
1690 3. (all) Show the members of this list.
1691 4. (user) Show the members of type USER.
1692 5. (list) Show the members of type LIST.
1693 6. (string) Show the members of type STRING.
1694 7. (verbose) Toggle Verbosity of Delete.
1695 r. (return) Return to previous menu.
1696 t. (toggle) Toggle logging on and off.
1703 add@\add_member_to_list
1704 remove@\delete_member_from_list
1705 all@\get_members_of_list
1706 user@\get_members_of_list
1707 list@\get_members_of_list
1708 string@\get_members_of_list
1712 @Center{ @b[Post Office Box Menu] }
1716 1. (show) Show a user's post office box.
1717 2. (set) Set (Add or Change) a user's post office box.
1718 3. (remove) Remove a user's post office box.
1719 4. (verbose) Toggle Verbosity of Delete.
1720 r. (return) Return to previous menu.
1721 t. (toggle) Toggle logging on and off.
1729 set@\get_pobox@\get_server_locations
1730 @\set_pobox_pop@\set_pobox
1731 remove@\delete_pobox
1735 @Center{ @b[Quota Menu] }
1739 1. (shdef) Show default user quota (in KB).
1740 2. (chdef) Change default user quota.
1741 3. (shquota) Show a user's disk quota on a filesystem.
1742 4. (addquota) Add a new disk quota for user on a filesystem.
1743 5. (chquota) Change a user's disk quota on a filesystem.
1744 6. (rmquota) Remove a user's disk quota on a filesystem.
1745 7. (verbose) Toggle Verbosity of Delete.
1746 r. (return) Return to previous menu.
1747 t. (toggle) Toggle logging on and off.
1755 chdef@\update_value@\get_value
1756 shquota@\get_nfs_quota
1757 addquota@\add_nfs_quota
1758 chquota@\get_nfs_quota@\update_nfs_quota
1759 rmquota@\get_nfs_quota@\delete_nfs_quota
1763 @Appendix(Menu Tree Diagram)