]> andersk Git - moira.git/blob - clients/moira/user.c
fixed adduser to check to see if a user with the same name already exists
[moira.git] / clients / moira / user.c
1 #if (!defined(lint) && !defined(SABER))
2   static char rcsid_module_c[] = "$Header$";
3 #endif lint
4
5 /*      This is the file user.c for the SMS Client, which allows a nieve
6  *      user to quickly and easily maintain most parts of the SMS database.
7  *      It Contains: Functions for manipulating user information.
8  *      
9  *      Created:        5/9/88
10  *      By:             Chris D. Peterson
11  *
12  *      $Source$
13  *      $Author$
14  *      $Header$
15  *      
16  *      Copyright 1988 by the Massachusetts Institute of Technology.
17  *
18  *      For further information on copyright and distribution 
19  *      see the file mit-copyright.h
20  */
21
22 #include <stdio.h>
23 #include <strings.h>
24 #include <sms.h>
25 #include <menu.h>
26
27 #include "mit-copyright.h"
28 #include "defs.h"
29 #include "f_defs.h"
30 #include "globals.h"
31 #include "infodefs.h"
32
33 #define LOGIN 0
34 #define UID   1
35 #define BY_NAME  2
36 #define CLASS 3
37
38 #define DEFAULT_SHELL "/bin/csh"
39 #define DEFAULT_CLASS "?"
40
41
42 /*      Function Name: UserState
43  *      Description: Convert a numeric state into a descriptive string.
44  *      Arguments: state value
45  *      Returns: pointer to statically allocated string.
46  */
47
48 static char *states[] = { "Not registered",
49                           "Active",
50                           "Half registered",
51                           "Marked for deletion",
52                           "Not registerable" };
53
54 static char *UserState(state)
55 int state;
56 {
57     if (state < 0 || state > 4)
58         return("Unknown");
59     return(states[state]);
60 }
61
62
63 /*      Function Name: PrintUserName
64  *      Description: Print name of a user.
65  *      Arguments: info - the information about a user.
66  *      Returns: none.
67  */
68
69 static void
70 PrintUserName(info)
71 char ** info;
72 {
73     char buf[BUFSIZ], print_buf[BUFSIZ];
74     sprintf(buf, "%s, %s %s", info[U_LAST], info[U_FIRST], info[U_MIDDLE]);
75     sprintf(print_buf, "%-40s User Name: %s", buf, info[U_NAME]);
76     Put_message(print_buf);
77 }
78
79 /*      Function Name: PrintUserInfo
80  *      Description: Prints Information about a user.
81  *      Arguments: info - an argument list with the user information
82  *                          in it.
83  *      Returns: none
84  */
85
86 static void
87 PrintUserInfo(info)
88 char ** info;
89 {
90     char name[BUFSIZ], buf[BUFSIZ];
91
92     sprintf(name, "%s, %s %s", info[U_LAST], info[U_FIRST], info[U_MIDDLE]);
93     sprintf(buf, "Login name: %-10s Full name: %s", info[U_NAME], name);
94     Put_message(buf);
95     sprintf(buf, "User id: %-13s Login shell %-15s Class: %s", 
96             info[U_UID], info[U_SHELL], info[U_CLASS]);
97     Put_message(buf);
98     sprintf(buf, "Account is: %-10s Encrypted MIT ID number: %s",
99             UserState(atoi(info[U_STATE])), info[U_MITID]);
100     Put_message(buf);
101     sprintf(buf, MOD_FORMAT, info[U_MODBY], info[U_MODTIME],info[U_MODWITH]);
102     Put_message(buf);
103 }
104
105 /*      Function Name: SetUserDefaults
106  *      Description: Sets the default values for add user.
107  *      Arguments: info - a blank user info array of char *'s.
108  *      Returns: args - the filled info structure.
109  */
110
111 static char **
112 SetUserDefaults(info)
113 char ** info;
114 {
115     info[U_NAME] = Strsave(UNIQUE_LOGIN);
116     info[U_UID] = Strsave(UNIQUE_UID);
117     info[U_SHELL] = Strsave(DEFAULT_SHELL);
118     info[U_LAST] = Strsave(DEFAULT_NONE);
119     info[U_FIRST] = Strsave(DEFAULT_NONE);
120     info[U_MIDDLE] = Strsave(DEFAULT_NONE);
121     info[U_STATE] = Strsave(DEFAULT_NO);
122     info[U_MITID] = Strsave(DEFAULT_NONE);
123     info[U_CLASS] = Strsave(DEFAULT_CLASS);
124     info[U_MODTIME] = info[U_MODBY] = info[U_MODWITH] = info[U_END] = NULL;
125     return(info);
126 }
127
128 /*      Function Name: AskUserInfo.
129  *      Description: This function askes the user for information about a 
130  *                   machine and saves it into a structure.
131  *      Arguments: info - a pointer the the structure to put the info into.
132  *                 flags - Flags asking us which info we want.
133  *      Returns: the args to pass to the query.
134  *      NOTES: the return args are not necessarily in the correct order to
135  *             use the #defined names (e.g args[UID] is not the uid anymore).
136  */
137
138 char **
139 AskUserInfo(info, name)
140 char ** info;
141 Bool name;
142 {
143     char temp_buf[BUFSIZ], *newname, *temp_ptr;
144
145     if (name) {
146         sprintf(temp_buf,"\nChanging Attributes of user %s.\n",info[U_NAME]);
147         Put_message(temp_buf);
148     } else {
149         struct qelem *elem = NULL;
150         char *argv[3];
151
152         GetValueFromUser("User's last name", &info[U_LAST]);
153         GetValueFromUser("User's first name", &info[U_FIRST]);
154         GetValueFromUser("User's middle name", &info[U_MIDDLE]);
155         argv[0] = info[U_FIRST];
156         argv[1] = info[U_LAST];
157         if (do_sms_query("get_user_by_name", 2, argv,
158                          StoreInfo, (char *) &elem) == 0) {
159             Put_message("A user by that name already exists in the database.");
160             Loop(QueueTop(elem), PrintUserInfo);
161             Loop(QueueTop(elem), FreeInfo);
162             FreeQueue(elem);
163             if (YesNoQuestion("Add new user anyway", TRUE) == FALSE)
164               return(NULL);
165         }
166     }
167     if (name) {
168         newname = Strsave(info[U_NAME]);
169         GetValueFromUser("The new login name for this user", &newname);
170     }
171     else
172         GetValueFromUser("Login name for this user", &info[U_NAME]);
173
174     GetValueFromUser("User's UID", &info[U_UID]);
175     GetValueFromUser("User's shell", &info[U_SHELL]);
176     if (name) {
177         GetValueFromUser("User's last name", &info[U_LAST]);
178         GetValueFromUser("User's first name", &info[U_FIRST]);
179         GetValueFromUser("User's middle name", &info[U_MIDDLE]);
180     }
181     GetValueFromUser("User's status", &info[U_STATE]);
182     temp_ptr = Strsave(info[U_MITID]);
183     Put_message("User's MIT ID number (type a new unencrypted number, or keep same encryption)");
184     GetValueFromUser("", &temp_ptr);
185     if ( strcmp( temp_ptr, info[U_MITID] ) != 0) {
186         EncryptID(temp_buf, temp_ptr, info[U_FIRST], info[U_LAST]);
187         free(info[U_MITID]);
188         info[U_MITID] = Strsave(temp_buf);
189     }
190     free(temp_ptr);
191     GetTypeFromUser("User's MIT Year (class)", "class", &info[U_CLASS]);
192     
193     FreeAndClear(&info[U_MODTIME], TRUE);
194     FreeAndClear(&info[U_MODBY], TRUE);
195     FreeAndClear(&info[U_MODWITH], TRUE);
196
197 /* 
198  * Slide the newname into the #2 slot, this screws up all future references 
199  * to this list, since we slip the pointer into a info list it gets freed 
200  * when the rest of the list gets freed.
201  */
202     if (name)                   
203         SlipInNewName(info, newname);
204
205     return(info);
206 }
207
208 /*      Function Name: GetUserInfo
209  *      Description: Stores the user information in a queue.
210  *      Arguments: type - type of field given to get info, one of:
211  *                        LOGIN, UID, BY_NAME, CLASS.
212  *                 name1 - name of thing specified by type (wildcards okay)
213  *                 name2 - other name, only used in get user by first and last.
214  *                         (wildcards okay).
215  *      Returns: the first element of the queue containing the user info.
216  */
217
218 struct qelem *
219 GetUserInfo(type, name1, name2)
220 int type;
221 char *name1, *name2;
222 {
223     char * args[2];
224     register int status;
225     struct qelem * elem = NULL;
226
227     switch(type) {
228     case LOGIN:
229         args[0] = name1;
230         if ( (status = do_sms_query("get_user_by_login", 1, args,
231                                     StoreInfo, (char *) &elem)) != 0) {
232             com_err(program_name, status, 
233                     " when attempting to get_user_by_login.");
234             return (NULL);               
235         }
236         break;
237     case UID:
238         args[0] = name1;
239         if ( (status = do_sms_query("get_user_by_uid", 1, args,
240                                     StoreInfo, (char *) &elem)) != 0) {
241             com_err(program_name, status, 
242                     " when attempting to get_user_by_uid.");
243             return (NULL);      
244         }
245         break;
246     case BY_NAME:
247         args[0] = name1;
248         args[1] = name2;    
249         if ( (status = do_sms_query("get_user_by_name", 2, args,
250                                     StoreInfo, (char *) &elem)) != 0) {
251             com_err(program_name, status, 
252                     " when attempting to get_user_by_name.");
253             return (NULL);      
254         }
255         break;
256     case CLASS:
257         args[0] = name1;
258         if ( (status = do_sms_query("get_user_by_class", 1, args,
259                                     StoreInfo, (char *) &elem)) != 0) {
260             com_err(program_name, status, 
261                     " when attempting to get_user_by_class.");
262             return (NULL);      
263         }
264         break;
265     }
266     return( QueueTop(elem) );
267 }
268
269 /*      Function Name: AddNewUser
270  *      Description: Adds a new user to the database.
271  *      Arguments: none.
272  *      Returns: DM_NORMAL.
273  */
274
275 /* ARGSUSED */
276 int
277 AddNewUser()
278 {
279     register int status;
280     char ** args, *info[MAX_ARGS_SIZE];
281
282     args = AskUserInfo(SetUserDefaults(info), FALSE);
283     if (args == NULL)
284       return(DM_NORMAL);
285     if ( (status = do_sms_query("add_user", CountArgs(args), 
286                                 args, Scream, (char *) NULL)) != SMS_SUCCESS)
287         com_err(program_name, status, " in add_user");
288     else
289         Put_message("New user added to database.");
290     FreeInfo(args);
291     return(DM_NORMAL);
292 }
293
294
295 /*      Function Name: GetLoginName
296  *      Description: Asks the user for a login name and reserves
297  *                   it with kerberous.
298  *      Arguments: none.
299  *      Returns: a malloced login name for the user.
300  */
301
302 static char *
303 GetLoginName()
304 {
305     char name[BUFSIZ];
306
307     Prompt_input("Login name for this user? ", name, BUFSIZ);
308     
309     Put_message(
310               "KERBEROS code not added, did not reserve name with kerberos.");
311
312     return(Strsave(name));
313 }
314
315
316 /*      Function Name: ChooseUser
317  *      Description: Choose a user from a list and return the uid.
318  *      Arguments: top - a queue of user information.
319  *      Returns: uid - the malloced uid of the user that was chosen.
320  */
321
322 static char *
323 ChooseUser(elem)
324 struct qelem * elem;
325 {
326     while (elem != NULL) {
327         char ** info = (char **)  elem->q_data;
328         PrintUserInfo(info);
329         switch(YesNoQuitQuestion("Is this the user you want (y/n/q)", FALSE)) {
330         case TRUE:
331             return(Strsave(info[U_UID]));
332         case FALSE:
333             break;
334         default:                /* quit or ^C. */
335             return(NULL);
336         }
337         elem = elem->q_forw;
338     }
339     return(NULL);
340 }
341
342 /*      Function Name: GetUidNumberFromName
343  *      Description: Gets the users uid number, from the name.
344  *      Arguments: none.
345  *      Returns: uid - a malloced string containing the uid.
346  */
347
348 static char *
349 GetUidNumberFromName()
350 {
351     char *args[5], *uid, first[BUFSIZ], last[BUFSIZ];
352     register int status;
353     struct qelem * top = NULL;
354     
355     Prompt_input("First Name: ", first, BUFSIZ);
356     Prompt_input("Last  Name: ", last, BUFSIZ);
357
358     args[0] = first;
359     args[1] = last;
360     
361     switch (status = do_sms_query("get_user_by_name", 2, args,
362                                   StoreInfo, (char *) &top)) {
363     case SMS_SUCCESS:
364         break;
365     case SMS_NO_MATCH:
366         Put_message("There is no user in the database with that name.");
367         return(NULL);
368     default:
369         com_err(program_name, status, " in get_user_by_name.");
370         return(NULL);
371     }
372     
373     top = QueueTop(top);
374     if (QueueCount(top) == 1) /* This is a unique name. */ {
375         char ** info = (char **) top->q_data;
376         Put_message("User ID Number retrieved for the user: ");
377         Put_message("");
378         PrintUserName(info);
379         uid = Strsave(info[U_UID]);
380         FreeQueue(top);
381         return(Strsave(uid));
382     }
383
384     Put_message("That name is not unique, choose the user that you want.");
385     uid = ChooseUser(top);
386     FreeQueue(top);
387     return(uid);
388 }
389
390 /*      Function Name: SetUserPassword
391  *      Description: Set the new kerberos password for this user.
392  *      Arguments: name - kerberos principle name for this user, (login name).
393  *      Returns: none.
394  */
395
396 static void
397 SetUserPassword(name)
398 char * name;
399 {
400     name = name;                        /* make saber happy. */
401     Put_message("Kerberos password not changed, code non-existant.");
402     /* clever message to call account_admin, if this fails. */
403 }
404
405 /*      Function Name:  GiveBackLogin
406  *      Description: Gives back previously reserved kerberous principle.
407  *      Arguments: name - principle to give back.
408  *      Returns: void.
409  */
410
411 static void
412 GiveBackLogin(name)
413 char * name;
414 {
415     name = name;                        /* make saber happy. */
416     Put_message("kerberos code not implimented, name not given back.");
417     /* send mail to db maintainer if this fails. */
418 }
419
420 /*      Function Name: RegisterUser
421  *      Description: This function registers a user.
422  *      Arguments: none.
423  *      Returns: DM_NORMAL.
424  */
425
426 int
427 RegisterUser()
428 {
429     char * args[MAX_ARGS_SIZE];
430     char *login, *fstype = NULL;
431     char temp_buf[BUFSIZ];
432     register int status;
433     
434     Put_message("This function has NO kerberos support, so stange things");
435     Put_message("may happen if you use it to register a user.");
436
437     switch (YesNoQuestion("Do you know the users UID Number (y/n)", FALSE)) {
438     case TRUE:
439         Prompt_input("What is the UID number of the user? ", temp_buf, BUFSIZ);
440         args[0] = Strsave(temp_buf);
441         break;
442     case FALSE:
443         if ( (args[0] = GetUidNumberFromName()) == NULL)
444             return(DM_NORMAL);
445         break;
446     default:
447         return(DM_NORMAL);
448     }
449
450     if ( ((login = args[1] = GetLoginName()) == NULL) ||
451         ( GetFSTypes(&fstype) == SUB_ERROR ) ) {
452         FreeInfo(args);    /* This work because the NULL temination is ok. */
453         return(DM_NORMAL);
454     }
455     args[2] = fstype;
456     args[3] = NULL;
457     
458     switch (status = do_sms_query("register_user", CountArgs(args),
459                                   args, Scream, (char *) NULL)) {
460     case SMS_SUCCESS:
461         sprintf(temp_buf, "User %s successfully registered.", login);
462         Put_message(temp_buf);
463         SetUserPassword(login);
464         break;
465     case SMS_IN_USE:
466         GiveBackLogin(login);
467         sprintf(temp_buf, "The username %s is already in use.", login);
468         Put_message(temp_buf);
469         break;
470     default:
471         com_err(program_name, status, " in register_user");
472         break;
473     }
474     FreeInfo(args);
475     return(DM_NORMAL);
476 }
477
478 /*      Function Name: RealUpdateUser
479  *      Description: actuall updates the user information.
480  *      Arguments: info - all current information for the user fields.
481  *                 junk - an UNUSED boolean.
482  *      Returns: none.
483  */
484
485 /* ARGSUSED */
486 static void
487 RealUpdateUser(info, junk)
488 char ** info;
489 Bool junk;
490 {
491     register int status;
492     char error_buf[BUFSIZ];
493     char ** args = AskUserInfo(info, TRUE);
494     
495     if ( (status = do_sms_query("update_user", CountArgs(args), 
496                                 args, Scream, (char *) NULL)) != SMS_SUCCESS) {
497         com_err(program_name, status, " in ModifyFields");
498         sprintf(error_buf, "User %s not updated due to errors.", info[NAME]);
499         Put_message(error_buf);
500     }
501 }
502
503 /*      Function Name: UpdateUser
504  *      Description: Modify some of the information about a user.
505  *      Arguments: argc, argv - login name of the user in argv[1].
506  *      Returns: DM_NORMAL.
507  */
508
509 /* ARGSUSED */
510 int
511 UpdateUser(argc, argv)
512 int argc;
513 char **argv;
514 {
515     struct qelem * elem;
516
517     elem = GetUserInfo(LOGIN, argv[1], (char *) NULL);
518     QueryLoop(elem, NullPrint, RealUpdateUser, "Update the user");
519     
520     FreeQueue(elem);
521     return(DM_NORMAL);
522 }
523
524 /*      Function Name: RealDeactivateUser
525  *      Description: sets the user's status to 3.
526  *      Arguments: info - all current information for the user fields
527  *                 one_item - indicates the user hasn't been queried yet
528  *      Returns: none.
529  */
530
531 static void
532 RealDeactivateUser(info, one_item)
533 char ** info;
534 Bool one_item;
535 {
536     register int status;
537     char txt_buf[BUFSIZ];
538     char * qargs[2];
539
540     if (one_item) {
541         sprintf(txt_buf, "Deactivate user %s (y/n)", info[NAME]);
542         if (!YesNoQuestion(txt_buf, 2))
543             return;
544     }
545
546     qargs[0] = info[NAME];
547     qargs[1] = "3";
548     if ((status = do_sms_query("update_user_status", 2, qargs, Scream,
549                                (char *) NULL)) != SMS_SUCCESS) {
550         com_err(program_name, status, " in update_user_status");
551         sprintf(txt_buf, "User %s not deactivated due to errors.", info[NAME]);
552         Put_message(txt_buf);
553     }
554 }
555
556
557 /*      Function Name: DeactivateUser
558  *      Description: sets the user's status to 3.
559  *      Arguments: argc, argv - login name of the user in argv[1].
560  *      Returns: DM_NORMAL.
561  */
562
563 /* ARGSUSED */
564 int
565 DeactivateUser(argc, argv)
566 int argc;
567 char **argv;
568 {
569     struct qelem * elem;
570
571     elem = GetUserInfo(LOGIN, argv[1], (char *) NULL);
572     QueryLoop(elem, NullPrint, RealDeactivateUser, "Deactivate user");
573     
574     FreeQueue(elem);
575     return(DM_NORMAL);
576 }
577
578
579 /* ------------------------- Top Menu ------------------------- */
580
581 /* DeleteUser() in delete.c */
582
583 /*      Function Name: DeleteUserByUid
584  *      Description: Deletes the user given a uid number.
585  *      Arguments: argc, argv - uid if user in argv[1].
586  *      Returns: DM_NORMAL.
587  *      NOTES: This just gets the username from the sms server 
588  *             and performs a DeleteUser().
589  */
590
591 int
592 DeleteUserByUid(argc, argv)
593 int argc;
594 char **argv;
595 {
596     int status;
597     struct qelem *elem = NULL;
598     char ** info;
599
600     if(!ValidName(argv[1]))
601         return(DM_NORMAL);
602     
603     if ( (status = do_sms_query("get_user_by_uid", 1, argv+1, StoreInfo,
604                                 (char * ) &elem)) != SMS_SUCCESS)
605         com_err(program_name, status, " in get_user_by_uid");
606     
607     info = (char **) elem->q_data;
608     argv[1] = info[U_NAME];
609
610     (void) DeleteUser(argc, argv);
611     return(DM_NORMAL);
612
613
614 /* ------------------------- Show User Information ------------------------- */
615
616 /*      Function Name: ShowUserByLogin
617  *      Description: Shows user information given a login name.
618  *      Arguments: argc, argv - login name in argv[1].
619  *      Returns: DM_NORMAL
620  */
621
622 /* ARGSUSED */
623 int
624 ShowUserByLogin(argc, argv)
625 int argc;
626 char *argv[];
627 {
628     struct qelem *top, *elem;
629
630     elem = top = GetUserInfo(LOGIN, argv[1], (char *) NULL);
631     Loop(elem, PrintUserInfo);
632
633     FreeQueue(top);
634     return (DM_NORMAL);
635 }
636
637 /*      Function Name: RetrieveUserByName
638  *      Description: Show information on a user give fist and/or last name.
639  *      Arguments: argc, argv - argv[1] - first name.
640  *                              argv[2] - last name.
641  *      Returns: DM_NORMAL.
642  */
643
644 /* ARGSUSED */
645 int
646 ShowUserByName(argc, argv)
647 int argc;
648 char *argv[];
649 {
650     struct qelem *top;
651     char buf[BUFSIZ];
652
653     top = GetUserInfo(BY_NAME, argv[1], argv[2]);
654
655     if (top == NULL)            /* if there was an error then return. */
656         return(DM_NORMAL);
657
658     if (!PromptWithDefault("Print full information, or just the names (f/n)?",
659                            buf, 2, "f"))
660         return(DM_NORMAL);
661
662     switch(buf[0]) {
663     case 'F':
664     case 'f':
665         Loop(top, PrintUserInfo);
666         break;
667     case 'N':
668     case 'n':
669         Loop(top, PrintUserName);
670         break;
671     }
672     
673     FreeQueue(top);
674     return (DM_NORMAL);
675 }
676
677 /*      Function Name: ShowUserByClass
678  *      Description: Shows real and login names of all users in class.
679  *      Arguments: argc, argv - argv[1] contains the class.
680  *      Returns: none.
681  */
682
683 /* ARGSUSED */
684 int
685 ShowUserByClass(argc, argv)
686 int argc;
687 char **argv;
688 {
689     struct qelem *top;
690
691     top = GetUserInfo(CLASS, argv[1], (char *) NULL);
692     Loop(top, PrintUserName);
693
694     FreeQueue(top);
695     return (DM_NORMAL);
696 }
This page took 0.089549 seconds and 5 git commands to generate.