1 #if (!defined(lint) && !defined(SABER))
2 static char rcsid_module_c[] = "$Header$";
5 /* This is the file user.c for allmaint, the SMS client that allows
6 * a user to maintaint most important parts of the SMS database.
7 * It Contains: the functions for usermaint.
10 * By: Chris D. Peterson
16 * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
18 * For further information on copyright and distribution
19 * see the file mit-copyright.h
28 #include "mit-copyright.h"
30 #include "allmaint_funcs.h"
40 static void PrintQuota(); /* prints Quota info. */
41 static void PrintUserInfo(); /* prints User info. */
42 static int PrintPOBoxes(); /* prints PO Box information. */
44 /* Function Name: AskUserInfo.
45 * Description: This function askes the user for information about a
46 * machine and saves it into a structure.
47 * Arguments: info - a pointer the the structure to put the info into.
48 * flags - Flags asking us which info we want.
49 * Returns: the args to pass to the query.
50 * NOTES: the return args are not necessarily in the correct order to
51 * use the #defined names (e.g args[UID] is not the uid anymore).
55 AskUserInfo(info, name)
59 char temp_buf[BUFSIZ], *newname;
61 sprintf(temp_buf,"\nChanging Attributes of user %s.\n",info[U_NAME]);
62 Put_message(temp_buf);
65 newname = Strsave(info[U_NAME]);
66 GetValueFromUser("The new login name for this user.", &newname);
68 GetValueFromUser("User's UID:", &info[U_UID]);
69 GetValueFromUser("User's shell:", &info[U_SHELL]);
70 GetValueFromUser("User's last name:", &info[U_LAST]);
71 GetValueFromUser("User's first name:", &info[U_FIRST]);
72 GetValueFromUser("User's middle name:", &info[U_MIDDLE]);
73 GetValueFromUser("User's status:", &info[U_STATE]);
74 GetValueFromUser("User's MIT ID number:", &info[U_MITID]);
75 RemoveHyphens(info[U_MITID]); /* zap'em */
76 GetValueFromUser("User's MIT Year (class):", &info[U_CLASS]);
78 FreeAndClear(&info[U_MODTIME], TRUE);
79 FreeAndClear(&info[U_MODBY], TRUE);
80 FreeAndClear(&info[U_MODWITH], TRUE);
83 * Slide the newname into the #2 slot, this screws up all future references
84 * to this list, since we slip the pointer into a info list it gets freed
85 * when the rest of the list gets freed.
88 SlipInNewName(info, newname);
93 /* Function Name: GetUserInfo
94 * Description: Stores the user information in a queue.
95 * Arguments: type - type of field given to get info, one of:
96 * LOGIN, UID, BY_NAME, CLASS.
97 * name1 - name of thing specified by type (wildcards okay)
98 * name2 - other name, only used in get user by first and last.
100 * Returns: the first element of the queue containing the user info.
104 GetUserInfo(type, name1, name2)
110 struct qelem * elem = NULL;
115 if ( (status = sms_query("get_user_by_login", 1, args,
116 StoreInfo, (char *) &elem)) != 0) {
117 com_err(program_name, status,
118 " when attempting to get_use_by_login.");
124 if ( (status = sms_query("get_user_by_uid", 1, args,
125 StoreInfo, (char *) &elem)) != 0) {
126 com_err(program_name, status,
127 " when attempting to get_use_by_uid.");
134 if ( (status = sms_query("get_user_by_name", 1, args,
135 StoreInfo, (char *) &elem)) != 0) {
136 com_err(program_name, status,
137 " when attempting to get_use_by_name.");
143 if ( (status = sms_query("get_user_by_class", 1, args,
144 StoreInfo, (char *) &elem)) != 0) {
145 com_err(program_name, status,
146 " when attempting to get_use_by_class.");
152 if ( (status = sms_query("get_nquotas_by_user", 1, args,
153 StoreInfo, (char *) &elem)) != 0) {
154 com_err(program_name, status, " in get_nfs_quotas_by_user");
159 return( QueueTop(elem) );
162 /* -------------------------- Change Menu -------------------------- */
164 /* Function Name: ModifyUser
165 * Description: Modify some of the information about a user.
166 * Arguments: argc, argv - login name of the user in argv[1].
167 * Returns: DM_NORMAL.
172 ModifyUser(argc, argv)
177 char *temp_buf, error_buf[BUFSIZ];
178 struct qelem * elem, * local;
180 local = elem = GetUserInfo(LOGIN, argv[1], (char *) NULL);
182 while (local != NULL) {
183 char ** info = (char **) local->q_data;
184 char ** args = AskUserInfo(info, TRUE);
186 if ( (status = sms_query("update_user", CountArgs(args),
187 args, Scream, NULL)) != 0) {
188 com_err(program_name, status, " in ModifyFields");
189 if (local->q_forw == NULL)
192 temp_buf = ", Continuing to next user";
193 sprintf(error_buf,"User %s not updated due to error%s.",
194 info[NAME], temp_buf);
195 Put_message(error_buf);
197 local = local->q_forw;
204 /* Function Name: POType
205 * Description: Asks the SMS server if it is of type pop, of
206 * of type local. If neither, we assume that it's
208 * Arguments: machine - a canonicalized machine name,
209 * Returns: the PO Type, one of: pop, local, foreign.
218 struct qelem *top, *elem = NULL;
221 status = sms_query("get_server_locations", 1, &type,
223 if (status && (status != SMS_NO_MATCH)) {
224 com_err(program_name, status, (char *) NULL);
225 return( (char *) NULL);
228 top = elem = QueueTop(elem);
229 while (elem != NULL) {
230 char ** info = (char **) elem->q_data;
231 if (strcmp (info[1], machine) == 0) {
233 return( Strsave("POP") );
238 return ( Strsave("SMTP") );
241 /* Function Name: ChangeUserPOBox
242 * Description: Changes The P.O. Box for a user.
243 * Arguments: argc, argv - the login name of the user in argv[1].
244 * Returns: DM_NORMAL.
249 ChangeUserPOBox(argc, argv)
254 struct qelem * poqueue, *local;
255 char *type, buf[BUFSIZ], *pohost;
259 sprintf(buf,"Current pobox for user %s: \n", argv[1]);
261 status = sms_query("get_pobox", 1, argv + 1, PrintPOBoxes, NULL);
262 if (status != SMS_NO_MATCH && status != 0) {
263 com_err(program_name, status, "in ChangeUserPOBox.");
266 else if (status == SMS_NO_MATCH)
267 Put_message("This user has no P.O. Box.");
269 if (YesNoQuestion("Shall we use the least loaded Post Office?", TRUE)) {
272 if ( status = sms_query ("get_server_host_info", 2, po,
273 StoreInfo, (char *) &poqueue) != 0) {
274 com_err(program_name, status,
275 " in ChangeUserPOBox (get_server_host_info).");
279 while (local != NULL) {
280 char ** args = (char **) local->q_data;
281 int new_space, old_space = -1 ;
282 if ( !isdigit(*args[6]) || !isdigit(*args[7]) )
284 "non-digit value in server_host_info, this is a bug.");
286 new_space = atoi(argv[7]) - atoi(args[6]);
287 if ( (new_space < old_space) || (old_space == -1) ) {
288 old_space = new_space;
289 strcpy(buf, args[1]);
292 local = local->q_forw;
294 pohost = Strsave(buf);
297 (void) sprintf(buf, "The Post Office %s was chosen.",
301 else if( (Prompt_input("Which Machine for Post Office?",
303 if ( (pohost = CanonicalizeHostname(buf)) == NULL) {
304 Put_message("\nNameserver doesn't know that machine, sorry.");
307 type = POType(pohost);
310 sprintf(buf, "%s %s's %s %s?", "Are you sure that you want to replace all",
311 argv[1], "P.O. Boxes\n with ** ONE ** on the machine", pohost);
318 if (status = sms_query("set_pobox", 4, po, Scream, NULL) != 0 )
319 com_err(program_name, status, " in ChangeUserPOBox");
321 Put_message("Operation Aborted.");
326 /* ------------------------- Top Menu ------------------------- */
328 /* delete user in delete.c */
330 /* Function Name: DeleteUserByUid
331 * Description: Deletes the user given a uid number.
332 * Arguments: argc, argv - uid if user in argv[1].
333 * Returns: DM_NORMAL.
338 DeleteUserByUid(argc, argv)
344 if (Confirm("Are you sure you want to remove this user"))
345 if ( (status = sms_query("delete_user_by_uid", 1, argv+1, Scream,
346 (char * ) NULL)) != 0)
347 com_err(program_name, status, " in DeleteUserByUid");
352 /* ------------------------- Show Quota Info ------------------------- */
354 /* Function Name: ShowDefaultQuota
355 * Description: This prints out a default quota for the system.
357 * Returns: DM_NORMAL.
364 static char *val[] = {"def_quota"};
366 if (status = sms_query("get_value", 1, val, Print, (char *) NULL) != 0)
367 com_err(program_name, status, " in ShowDefaultQuota");
372 /* Function Name: ShowUserQuota
373 * Description: Shows the quota of a user.
374 * Arguments: argc, argv - users login name is argv[1].
380 ShowUserQuota(argc, argv)
384 struct qelem *elem, *top;
385 top = elem = GetUserInfo(QUOTA, argv[1], (char *) NULL);
387 while (elem != NULL) {
388 char ** info = (char **) elem->q_data;
396 /* Function Name: ChangeDefaultQuota
397 * Description: Changes the System Wide default quota.
398 * Arguments: argc, argv - New quota in argv[1].
399 * Returns: DM_NORMAL.
404 ChangeDefaultQuota(argc, argv)
410 static char *newval[] = {
411 "update_value", "def_quota", NULL,
415 "Are you sure that you want to change the default quota\n",
416 "for all new users? (y/n) ");
419 if (status = sms_query("update_value", 3, newval, Scream, NULL) != 0)
420 com_err(program_name, status, " in update_value");
423 Put_message("Quota not changed.");
428 /* ---------------------- User Locker Manipultation -------------------- */
430 /* Function Name: AddUserLocker
431 * Description: Add a new locker for a user.
432 * Arguments: arc, argv -
433 * argv[1] login name of user.
434 * argv[2] server host name.
435 * argv[3] Directory on host.
436 * argv[4] quota in Kb.
437 * Returns: DM_NORMAL.
442 AddUserLocker(argc, argv)
453 args[1] = CanonicalizeHostname(argv[2]);
454 if (args[1] == (char *)NULL) {
455 Put_message("Could not canonicalize hostname; continuing..");
459 if (status = sms_query("add_locker", 4, args, Scream, NULL) != 0)
460 com_err(program_name, status, " in add_user_locker");
465 /* needs to be fixed - CDP 6/10/88 */
467 /* Function Name: DeleteUserLocker
468 * Description: Deletes a locker - BOOM.
469 * Arguments: arc, argv - the name of the locker in argv[1]/
470 * Returns: DM_NORMAL.
475 DeleteUserLocker(argc, argv)
480 if (status = sms_query("delete_locker", 1, argv + 1,
481 Scream, (char *)NULL) != 0)
482 com_err(program_name, status, " in delete_locker");
487 /* Function Name: ChangeUserQuota
488 * Description: This function allows all quotas to be updated for a user.
489 * Arguments: arg, argv - the name of the user in argv[1].
490 * Returns: DM_NORMAL.
495 ChangeUserQuota(argc, argv)
500 char error_buf[BUFSIZ];
501 struct qelem *elem, *local;
503 elem = GetUserInfo(QUOTA, argv[1], (char *) NULL);
506 while (local != NULL) {
508 info = (char **) local->q_data;
510 GetValueFromUser("New quota (in KB): ", &info[Q_QUOTA]);
512 if (status = sms_query("update_nfs_quota", 3, info,
513 Scream, (char *) NULL) != 0) {
514 com_err(program_name, status, " in update_nfs_quota");
515 sprintf(error_buf,"Could not perform quota change on %s",
517 Put_message(error_buf);
519 local = local->q_forw;
525 /* Function Name: ShowUserByLogin
526 * Description: Shows user information given a login name.
527 * Arguments: argc, argv - login name in argv[1].
533 ShowUserByLogin(argc, argv)
537 struct qelem *top, *elem;
539 elem = top = GetUserInfo(LOGIN, argv[1], (char *) NULL);
540 while (elem != NULL) {
541 PrintUserInfo( (char **) elem->q_data, FALSE);
549 /* Function Name: RetrieveUserByName
550 * Description: Show information on a user give fist and/or last name.
551 * Arguments: argc, argv - argv[1] - first name.
552 * argv[2] - last name.
553 * Returns: DM_NORMAL.
558 ShowUserByName(argc, argv)
562 struct qelem *top, *elem;
565 elem = top = GetUserInfo(BY_NAME, argv[1], argv[2]);
567 if (!PromptWithDefault("Print full information, or just the names (F/N)?",
571 while (elem != NULL) {
575 PrintUserInfo( (char **) elem->q_data, FALSE);
579 PrintUserInfo( (char **) elem->q_data, TRUE);
589 /* Function Name: ShowUserByClass
590 * Description: Shows real and login names of all users in class.
591 * Arguments: argc, argv - argv[1] contains the class.
597 ShowUserByClass(argc, argv)
601 struct qelem *top, *elem;
603 elem = top = GetUserInfo(CLASS, argv[1], (char *) NULL);
605 while (elem != NULL) {
606 PrintUserInfo( (char **) elem->q_data, TRUE);
615 /* Function Name: PrintQuota
616 * Description: Prints a users quota information.
617 * Arguments: info - a pointer to the quota information:
627 sprintf(buf, "Machine: %s\t\tDirectory: %s\t\tQuota: %s",
628 info[Q_MACHINE], info[Q_DIRECTORY], info[Q_QUOTA]);
632 /* Function Name: PrintPOBoxes
633 * Description: Yet another specialized print function.
634 * Arguments: argc, argv -
635 * argv[0] - login name.
638 * argv[3] - box name.
645 PrintPOBoxes(argc, argv, junk)
651 /* no newline 'cause Put_message adds one */
653 (void) sprintf(buf, "Address: %s@%s\t\tType: %s", argv[PO_BOX],
654 argv[PO_MACHINE], argv[PO_TYPE]);
655 (void) Put_message(buf);
660 /* Function Name: PrintUserInfo
661 * Description: Prints Information about a user.
662 * Arguments: info - an argument list with the user information
664 * name_only - if TRUE then print only the users name.
669 PrintUserInfo(info, name_only)
676 sprintf(buf, "%s, %s %s", info[U_LAST],
677 info[U_FIRST], info[U_MIDDLE]);
678 sprintf(buf, "%-40s/tUser Name: %s", buf, info[U_NAME]);
683 "Login name: %-10s/tUser id: %-10s\tLogin shell %s",
684 info[U_NAME], info[U_UID], info[U_SHELL]);
685 (void) Put_message(buf);
686 (void) sprintf(buf, "Full name: %s %s %s\tClass: %s",
687 info[U_FIRST], info[U_MIDDLE],
688 info[U_LAST], info[U_CLASS]);
689 (void) Put_message(buf);
691 "Account status: %s\tEncrypted MIT ID number: %s",
692 atoi(info[U_STATE]) ? "active" : "inactive",
694 (void) Put_message(buf);
695 (void) sprintf(buf, "Last Modification by %s at %s with %s.",
696 info[U_MODBY], info[U_MODTIME], info[U_MODWITH]);
697 (void) Put_message(buf);
705 * c-continued-statement-offset: 4
707 * c-argdecl-indent: 4