]> andersk Git - moira.git/blob - clients/moira/attach.c
If a user specified a member that isn't a LIST, a USER, or a foreign
[moira.git] / clients / moira / attach.c
1 /* $Id$
2  *
3  *      This is the file attach.c for the Moira Client, which allows users
4  *      to quickly and easily maintain most parts of the Moira database.
5  *      It Contains: Functions for maintaining data used by Hesiod
6  *                   to map courses/projects/users to their file systems,
7  *                   and maintain filesys info.
8  *
9  *      Created:        5/4/88
10  *      By:             Chris D. Peterson
11  *
12  * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
13  * For copying and distribution information, please see the file
14  * <mit-copyright.h>.
15  */
16
17 #include <mit-copyright.h>
18 #include <moira.h>
19 #include <moira_site.h>
20
21 #include "defs.h"
22 #include "f_defs.h"
23 #include "globals.h"
24
25 #include <sys/stat.h>
26
27 #include <ctype.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif /* HAVE_UNISTD_H */
34
35 RCSID("$Header$");
36
37 char *canonicalize_cell(char *c);
38 int GetAliasValue(int argc, char **argv, void *retval);
39 void RealDeleteFS(char **info, Bool one_item);
40 char *SortAfter(struct mqelem *elem, int count);
41 void RealDeleteFSAlias(char **info, Bool one_item);
42
43 #define FS_ALIAS_TYPE "FILESYS"
44
45 #define LABEL        0
46 #define MACHINE      1
47 #define GROUP        2
48 #define ALIAS        3
49 #define ALIAS_CHECK  4
50 #define FS_ALIASES   5
51
52 #define NO_MACHINE       ("[NONE]")
53
54 #define DEFAULT_TYPE     ("AFS")
55 #define DEFAULT_MACHINE  DEFAULT_NONE
56 #define DEFAULT_PACK     DEFAULT_NONE
57 #define DEFAULT_ACCESS   ("w")
58 #define DEFAULT_COMMENTS DEFAULT_COMMENT
59 #define DEFAULT_OWNER    (user)
60 #define DEFAULT_OWNERS   (user)
61 #define DEFAULT_CREATE   DEFAULT_YES
62 #define DEFAULT_L_TYPE   ("PROJECT")
63 #define DEFAULT_CELL     ("athena.mit.edu")
64
65 /*      Function Name: SetDefaults
66  *      Description: sets the default values for filesystem additions.
67  *      Arguments: info - an array of char pointers to recieve defaults.
68  *      Returns: char ** (this array, now filled).
69  */
70
71 static char **SetDefaults(char **info, char *name)
72 {
73   char buf[BUFSIZ];
74
75   info[FS_NAME] =     strdup(name);
76   info[FS_TYPE] =     strdup(DEFAULT_TYPE);
77   info[FS_MACHINE] =  strdup(DEFAULT_MACHINE);
78   info[FS_PACK] =     strdup(DEFAULT_PACK);
79   sprintf(buf, "/mit/%s", name);
80   info[FS_M_POINT] =  strdup(buf);
81   info[FS_ACCESS] =   strdup(DEFAULT_ACCESS);
82   info[FS_COMMENTS] = strdup(DEFAULT_COMMENTS);
83   info[FS_OWNER] =    strdup(DEFAULT_OWNER);
84   info[FS_OWNERS] =   strdup(DEFAULT_OWNERS);
85   info[FS_CREATE] =   strdup(DEFAULT_CREATE);
86   info[FS_L_TYPE] =   strdup(DEFAULT_L_TYPE);
87   info[FS_MODTIME] = info[FS_MODBY] = info[FS_MODWITH] = info[FS_END] = NULL;
88   return info;
89 }
90
91 /*      Function Name: GetFSInfo
92  *      Description: Stores the info in a queue.
93  *      Arguments: type - type of information to get.
94  *                 name - name of the item to get information on.
95  *      Returns: a pointer to the first element in the queue.
96  */
97
98 static struct mqelem *GetFSInfo(int type, char *name)
99 {
100   int stat;
101   struct mqelem *elem = NULL;
102   char *args[5];
103
104   switch (type)
105     {
106     case LABEL:
107       if ((stat = do_mr_query("get_filesys_by_label", 1, &name,
108                               StoreInfo, &elem)))
109         {
110           com_err(program_name, stat, " in GetFSInfo");
111           return NULL;
112         }
113       break;
114     case MACHINE:
115       if ((stat = do_mr_query("get_filesys_by_machine", 1, &name,
116                               StoreInfo, &elem)))
117         {
118           com_err(program_name, stat, " in GetFSInfo");
119           return NULL;
120         }
121       break;
122     case GROUP:
123       if ((stat = do_mr_query("get_filesys_by_group", 1, &name,
124                               StoreInfo, &elem)))
125         {
126           com_err(program_name, stat, " in GetFSInfo");
127           return NULL;
128         }
129       break;
130     case ALIAS:
131     case ALIAS_CHECK:
132       args[ALIAS_NAME] = name;
133       args[ALIAS_TYPE] = FS_ALIAS_TYPE;
134       args[ALIAS_TRANS] = "*";
135       if ((stat = do_mr_query("get_alias", 3, args, StoreInfo, &elem)))
136         {
137           if (type != ALIAS_CHECK || stat != MR_NO_MATCH)
138             com_err(program_name, stat, " in get_alias.");
139           return NULL;
140         }
141       break;
142     case FS_ALIASES:
143       args[ALIAS_NAME] = "*";
144       args[ALIAS_TYPE] = FS_ALIAS_TYPE;
145       args[ALIAS_TRANS] = name;
146       if ((stat = do_mr_query("get_alias", 3, args, StoreInfo, &elem)))
147         {
148           if (stat != MR_NO_MATCH)
149             com_err(program_name, stat, " in get_alias.");
150           return NULL;
151         }
152       break;
153     }
154
155   return QueueTop(elem);
156 }
157
158 /*      Function Name: PrintFSAlias
159  *      Description: Prints a filesystem alias
160  *      Arguments: info - an array contains the strings of info.
161  *      Returns: the name of the filesys - used be QueryLoop().
162  */
163
164 static char *PrintFSAlias(char **info)
165 {
166   char buf[BUFSIZ];
167
168   sprintf(buf, "Alias: %-25s Filesystem: %s", info[ALIAS_NAME],
169           info[ALIAS_TRANS]);
170   Put_message(buf);
171   return info[ALIAS_NAME];
172 }
173
174 static char aliasbuf[256];
175
176 static char *PrintFSAliasList(char **info)
177 {
178   if (strlen(aliasbuf) == 0)
179     snprintf(aliasbuf, sizeof(aliasbuf), "Aliases: %s", info[ALIAS_NAME]);
180   else
181     {
182       strncat(aliasbuf, ", ", sizeof(aliasbuf));
183       strncat(aliasbuf, info[ALIAS_NAME], sizeof(aliasbuf));
184     }
185 }
186
187 static char labelbuf[256];
188
189 static char *GetFSLabel(char **info)
190 {
191   snprintf(labelbuf, sizeof(labelbuf), info[ALIAS_TRANS]);
192 }
193
194 static int fsgCount = 1;
195
196 static void PrintFSGMembers(char **info)
197 {
198   char print_buf[BUFSIZ];
199
200   sprintf(print_buf, "  %d. Filesystem: %-32s (sort key: %s)",
201           fsgCount++, info[0], info[1]);
202   Put_message(print_buf);
203 }
204
205
206 /*      Function Name: PrintFSInfo
207  *      Description: Prints the filesystem information.
208  *      Arguments: info - a pointer to the filesystem information.
209  *      Returns: none.
210  */
211
212 static char *PrintFSInfo(char **info)
213 {
214   char print_buf[BUFSIZ];
215   struct mqelem *top;
216
217   FORMFEED;
218
219   if (!strcmp(info[FS_TYPE], "FSGROUP") || !strcmp(info[FS_TYPE], "MUL"))
220     {
221       int stat;
222       struct mqelem *elem = NULL;
223
224       if (!strcmp(info[FS_TYPE], "MUL"))
225         sprintf(print_buf, "%20s Multiple Filesystem: %s", " ", info[FS_NAME]);
226       else
227         sprintf(print_buf, "%20s Filesystem Group: %s", " ", info[FS_NAME]);
228       Put_message(print_buf);
229
230       top = GetFSInfo(FS_ALIASES, info[FS_NAME]);
231       if (top != NULL) {
232         *aliasbuf = 0;
233         Loop(top, (void (*)(char **))PrintFSAliasList);
234         Put_message(aliasbuf);
235         FreeQueue(top);         /* clean the queue. */
236       }
237
238       sprintf(print_buf, "Comments: %s", info[FS_COMMENTS]);
239       Put_message(print_buf);
240       sprintf(print_buf, MOD_FORMAT, info[FS_MODBY], info[FS_MODTIME],
241               info[FS_MODWITH]);
242       Put_message(print_buf);
243       Put_message("Containing the filesystems (in order):");
244       if ((stat = do_mr_query("get_fsgroup_members", 1, &info[FS_NAME],
245                               StoreInfo, &elem)))
246         {
247           if (stat == MR_NO_MATCH)
248             Put_message("    [no members]");
249           else
250             com_err(program_name, stat, " in PrintFSInfo");
251         }
252       else
253         {
254           fsgCount = 1;
255           Loop(QueueTop(elem), PrintFSGMembers);
256           FreeQueue(elem);
257         }
258     }
259   else
260     {
261       sprintf(print_buf, "%20s Filesystem: %s", " ", info[FS_NAME]);
262       Put_message(print_buf);
263
264       top = GetFSInfo(FS_ALIASES, info[FS_NAME]);
265       if (top != NULL) {
266         *aliasbuf = 0;
267         Loop(top, (void (*)(char **))PrintFSAliasList);
268         Put_message(aliasbuf);
269         FreeQueue(top);         /* clean the queue. */
270       }
271
272       sprintf(print_buf, "Type: %-40s Machine: %-15s",
273               info[FS_TYPE], info[FS_MACHINE]);
274       Put_message(print_buf);
275       sprintf(print_buf, "Default Access: %-2s Packname: %-17s Mountpoint %s ",
276               info[FS_ACCESS], info[FS_PACK], info[FS_M_POINT]);
277       Put_message(print_buf);
278       sprintf(print_buf, "Comments: %s", info[FS_COMMENTS]);
279       Put_message(print_buf);
280       sprintf(print_buf, "User Ownership: %-30s Group Ownership: %s",
281               info[FS_OWNER], info[FS_OWNERS]);
282       Put_message(print_buf);
283       sprintf(print_buf, "Update Fileserver: %-27s Locker Type: %s",
284               atoi(info[FS_CREATE]) ? "ON" : "OFF", info[FS_L_TYPE]);
285       Put_message(print_buf);
286       sprintf(print_buf, MOD_FORMAT, info[FS_MODBY], info[FS_MODTIME],
287               info[FS_MODWITH]);
288       Put_message(print_buf);
289     }
290   return info[FS_NAME];
291 }
292
293 char *canonicalize_cell(char *c)
294 {
295 #ifdef _WIN32
296   return c;
297 #else /* !_WIN32 */
298   struct stat stbuf;
299   char path[512];
300   int count;
301
302   sprintf(path, "/afs/%s", c);
303   if (lstat(path, &stbuf) || !stbuf.st_mode & S_IFLNK)
304     return c;
305   count = readlink(path, path, sizeof(path));
306   if (count < 1)
307     return c;
308   path[count] = 0;
309   free(c);
310   return strdup(path);
311 #endif /* _WIN32 */
312 }
313
314
315 int GetAliasValue(int argc, char **argv, void *retval)
316 {
317   *(char **)retval = strdup(argv[2]);
318   return MR_CONT;
319 }
320
321 /*      Function Name: AskFSInfo.
322  *      Description: This function askes the user for information about a
323  *                   machine and saves it into a structure.
324  *      Arguments: info - a pointer the the structure to put the
325  *                             info into.
326  *                 name - add a newname field? (T/F)
327  *      Returns: none.
328  */
329
330 static char **AskFSInfo(char **info, Bool name)
331 {
332   char temp_buf[BUFSIZ], *newname, access_type[32];
333   int fsgroup = 0, newdefaults = 0;
334
335   Put_message("");
336   sprintf(temp_buf, "Changing Attributes of filesystem %s.", info[FS_NAME]);
337   Put_message(temp_buf);
338   Put_message("");
339
340   if (name)
341     {
342       newname = strdup(info[FS_NAME]);
343       if (GetValueFromUser("The new name for this filesystem",
344                            &newname) == SUB_ERROR)
345         return NULL;
346     }
347
348   strcpy(temp_buf, info[FS_TYPE]);
349   if (GetTypeFromUser("Filesystem's Type", "filesys", &info[FS_TYPE]) ==
350       SUB_ERROR)
351     return NULL;
352   if (!strcasecmp(info[FS_TYPE], "FSGROUP") ||
353       !strcasecmp(info[FS_TYPE], "MUL"))
354     fsgroup++;
355   if (strcasecmp(info[FS_TYPE], temp_buf))
356     newdefaults++;
357   if (fsgroup)
358     {
359       free(info[FS_MACHINE]);
360       info[FS_MACHINE] = strdup(NO_MACHINE);
361     }
362   else
363     {
364       if (!strcasecmp(info[FS_TYPE], "AFS"))
365         {
366           if (!name || newdefaults)
367             {
368               free(info[FS_MACHINE]);
369               info[FS_MACHINE] = strdup(DEFAULT_CELL);
370             }
371           if (GetValueFromUser("Filesystem's Cell", &info[FS_MACHINE]) ==
372                 SUB_ERROR)
373             return NULL;
374           info[FS_MACHINE] = canonicalize_cell(info[FS_MACHINE]);
375         }
376       else
377         {
378           if (GetValueFromUser("Filesystem's Machine", &info[FS_MACHINE]) ==
379               SUB_ERROR)
380             return NULL;
381           info[FS_MACHINE] = canonicalize_hostname(info[FS_MACHINE]);
382         }
383     }
384   if (!fsgroup)
385     {
386       if (!strcasecmp(info[FS_TYPE], "AFS"))
387         {
388           char *path, *args[3], *p;
389           int status, depth;
390           if (GetTypeFromUser("Filesystem's lockertype", "lockertype",
391                               &info[FS_L_TYPE]) == SUB_ERROR)
392             return NULL;
393           if (!name || newdefaults)
394             {
395               free(info[FS_PACK]);
396               lowercase(info[FS_MACHINE]);
397               sprintf(temp_buf, "%s:%s", info[FS_MACHINE], info[FS_L_TYPE]);
398               args[0] = temp_buf;
399               args[1] = "AFSPATH";
400               args[2] = "*";
401               path = "???";
402               status = do_mr_query("get_alias", 3, args, GetAliasValue, &path);
403               if (status == MR_SUCCESS)
404                 {
405                   p = strchr(path, ':');
406                   if (p)
407                     {
408                       *p = '\0';
409                       depth = atoi(++p);
410                     }
411                   else
412                     depth = 0;
413                   sprintf(temp_buf, "/afs/%s/%s", info[FS_MACHINE], path);
414                   if (depth >= 0)
415                     {
416                       for (p = info[FS_NAME];
417                            *p && (p - info[FS_NAME]) < depth; p++)
418                         {
419                           if (islower(*p))
420                             {
421                               strcat(temp_buf, "/x");
422                               temp_buf[strlen(temp_buf) - 1] = *p;
423                             }
424                           else
425                             {
426                               sprintf(temp_buf, "/afs/%s/%s/other",
427                                       info[FS_MACHINE], path);
428                               break;
429                             }
430                         }
431                     }
432                   else if (depth == -1)
433                     {
434                       if (isdigit(info[FS_NAME][0]))
435                         {
436                           strcat(temp_buf, "/");
437                           depth = strlen(temp_buf);
438                           for (p = info[FS_NAME]; *p && isdigit(*p); p++)
439                             {
440                               temp_buf[depth++] = *p;
441                               temp_buf[depth] = 0;
442                             }
443                         }
444                       else
445                         strcat(temp_buf, "/other");
446                     }
447                   else
448                     {
449                         /* no default */
450                     }
451                   strcat(temp_buf, "/");
452                   strcat(temp_buf, info[FS_NAME]);
453                   free(path);
454                 }
455               else
456                 {
457                   sprintf(temp_buf, "/afs/%s/%s/%s", info[FS_MACHINE],
458                           lowercase(info[FS_L_TYPE]), info[FS_NAME]);
459                 }
460               info[FS_PACK] = strdup(temp_buf);
461             }
462         }
463       if (GetValueFromUser("Filesystem's Pack Name", &info[FS_PACK]) ==
464           SUB_ERROR)
465         return NULL;
466       if (GetValueFromUser("Filesystem's Mount Point", &info[FS_M_POINT]) ==
467           SUB_ERROR)
468         return NULL;
469       sprintf(access_type, "fs_access_%s", info[FS_TYPE]);
470       if (GetTypeFromUser("Filesystem's Default Access", access_type,
471                           &info[FS_ACCESS]) == SUB_ERROR)
472         return NULL;
473     }
474   if (GetValueFromUser("Comments about this Filesystem", &info[FS_COMMENTS])
475       == SUB_ERROR)
476     return NULL;
477   if (GetValueFromUser("Filesystem's owner (user)", &info[FS_OWNER]) ==
478       SUB_ERROR)
479     return NULL;
480   if (GetValueFromUser("Filesystem's owners (group)", &info[FS_OWNERS]) ==
481       SUB_ERROR)
482     return NULL;
483   if (!fsgroup)
484     if (GetYesNoValueFromUser("Propagate changes to fileserver",
485                               &info[FS_CREATE]) == SUB_ERROR)
486       return NULL;
487   if (strcasecmp(info[FS_TYPE], "AFS"))
488     {
489       if (GetTypeFromUser("Filesystem's lockertype", "lockertype",
490                           &info[FS_L_TYPE]) == SUB_ERROR)
491         return NULL;
492     }
493
494   FreeAndClear(&info[FS_MODTIME], TRUE);
495   FreeAndClear(&info[FS_MODBY], TRUE);
496   FreeAndClear(&info[FS_MODWITH], TRUE);
497
498   if (name)                     /* slide the newname into the #2 slot. */
499     SlipInNewName(info, newname);
500
501   return info;
502 }
503
504
505 /* --------------- Filesystem Menu ------------- */
506
507 /*      Function Name: GetFS
508  *      Description: Get Filesystem information by name.
509  *      Arguments: argc, argv - name of filsys in argv[1].
510  *      Returns: DM_NORMAL.
511  */
512
513 int GetFS(int argc, char **argv)
514 {
515   struct mqelem *top;
516   char *fs_label;
517
518   fs_label = argv[1];
519
520   top = GetFSInfo(ALIAS_CHECK, argv[1]);
521   if (top != NULL) {
522     Loop(top, (void (*)(char **))GetFSLabel);
523     fs_label = labelbuf;
524   }
525
526   top = GetFSInfo(LABEL, fs_label); /* get info. */
527   Loop(top, (void (*)(char **))PrintFSInfo);
528   FreeQueue(top);               /* clean the queue. */
529   return DM_NORMAL;
530 }
531
532 /*      Function Name: GetFSM
533  *      Description: Get Filesystem information by machine.
534  *      Arguments: argc, argv - name of server in argv[1].
535  *      Returns: DM_NORMAL.
536  */
537
538 int GetFSM(int argc, char **argv)
539 {
540   struct mqelem *top;
541
542   argv[1] = canonicalize_hostname(strdup(argv[1]));
543   top = GetFSInfo(MACHINE, argv[1]); /* get info. */
544   Loop(top, (void (*)(char **))PrintFSInfo);
545   FreeQueue(top);               /* clean the queue. */
546   return DM_NORMAL;
547 }
548
549 /*      Function Name: RealDeleteFS
550  *      Description: Does the real deletion work.
551  *      Arguments: info - array of char *'s containing all useful info.
552  *                 one_item - a Boolean that is true if only one item
553  *                              in queue that dumped us here.
554  *      Returns: none.
555  */
556
557 void RealDeleteFS(char **info, Bool one_item)
558 {
559   int stat;
560   char temp_buf[BUFSIZ];
561
562   /*
563    * Deletions are performed if the user hits 'y' on a list of multiple
564    * filesystem, or if the user confirms on a unique alias.
565    */
566   sprintf(temp_buf, "Are you sure that you want to delete filesystem %s",
567           info[FS_NAME]);
568   if (!one_item || Confirm(temp_buf))
569     {
570       if ((stat = do_mr_query("delete_filesys", 1,
571                               &info[FS_NAME], NULL, NULL)))
572         com_err(program_name, stat, " filesystem not deleted.");
573       else
574         Put_message("Filesystem deleted.");
575     }
576   else
577     Put_message("Filesystem not deleted.");
578 }
579
580 /*      Function Name: DeleteFS
581  *      Description: Delete a filesystem give its name.
582  *      Arguments: argc, argv - argv[1] is the name of the filesystem.
583  *      Returns: none.
584  */
585
586 int DeleteFS(int argc, char **argv)
587 {
588   struct mqelem *elem = GetFSInfo(LABEL, argv[1]);
589   QueryLoop(elem, PrintFSInfo, RealDeleteFS, "Delete the Filesystem");
590
591   FreeQueue(elem);
592   return DM_NORMAL;
593 }
594
595 /*      Function Name: RealChangeFS
596  *      Description: performs the actual change to the filesys.
597  *      Arguments: info - the information
598  *                 junk - an unused boolean.
599  *      Returns: none.
600  */
601
602 static void RealChangeFS(char **info, Bool junk)
603 {
604   int stat;
605   char **args;
606   extern Menu nfsphys_menu;
607
608   args = AskFSInfo(info, TRUE);
609   if (!args)
610     {
611       Put_message("Aborted.");
612       return;
613     }
614   stat = do_mr_query("update_filesys", CountArgs(args), args, NULL, NULL);
615   switch (stat)
616     {
617     case MR_NFS:
618       Put_message("That NFS filesystem is not exported.");
619       if (YesNoQuestion("Fix this now (Y/N)", TRUE) == TRUE)
620         {
621           Do_menu(&nfsphys_menu, 0, NULL);
622           if (YesNoQuestion("Retry filesystem update now (Y/N)", TRUE) == TRUE)
623             {
624               if ((stat = do_mr_query("update_filesys", CountArgs(args), args,
625                                       NULL, NULL)))
626                 com_err(program_name, stat, " filesystem not updated");
627               else
628                 Put_message("filesystem sucessfully updated.");
629             }
630         }
631       break;
632     case MR_SUCCESS:
633       break;
634     default:
635       com_err(program_name, stat, " in UpdateFS");
636     }
637 }
638
639 /*      Function Name: ChangeFS
640  *      Description: change the information in a filesys record.
641  *      Arguments: arc, argv - value of filsys in argv[1].
642  *      Returns: DM_NORMAL.
643  */
644
645 int ChangeFS(int argc, char **argv)
646 {
647   struct mqelem *elem = GetFSInfo(LABEL, argv[1]);
648   QueryLoop(elem, NullPrint, RealChangeFS, "Update the Filesystem");
649
650   FreeQueue(elem);
651   return DM_NORMAL;
652 }
653
654 /*      Function Name: AddFS
655  *      Description: change the information in a filesys record.
656  *      Arguments: arc, argv - name of filsys in argv[1].
657  *      Returns: DM_NORMAL.
658  */
659
660 int AddFS(int argc, char **argv)
661 {
662   char *info[MAX_ARGS_SIZE], **args, buf[BUFSIZ];
663   int stat;
664   extern Menu nfsphys_menu;
665
666   if (!ValidName(argv[1]))
667     return DM_NORMAL;
668
669   if (!(stat = do_mr_query("get_filesys_by_label", 1, argv + 1,
670                               NULL, NULL)))
671     {
672       Put_message ("A Filesystem by that name already exists.");
673       return DM_NORMAL;
674     }
675   else if (stat != MR_NO_MATCH)
676     {
677       com_err(program_name, stat, " in AddFS");
678       return DM_NORMAL;
679     }
680
681   if (!(args = AskFSInfo(SetDefaults(info, argv[1]), FALSE)))
682     {
683       Put_message("Aborted.");
684       return DM_NORMAL;
685     }
686
687   stat = do_mr_query("add_filesys", CountArgs(args), args, NULL, NULL);
688   switch (stat)
689     {
690     case MR_NFS:
691       Put_message("That NFS filesystem is not exported.");
692       if (YesNoQuestion("Fix this now (Y/N)", TRUE) == TRUE)
693         {
694           Do_menu(&nfsphys_menu, 0, NULL);
695           if (YesNoQuestion("Retry filesystem creation now (Y/N)", TRUE)
696               == TRUE) {
697             if ((stat = do_mr_query("add_filesys", CountArgs(args), args,
698                                     NULL, NULL)))
699               com_err(program_name, stat, " in AddFS");
700             else
701               Put_message("Created.");
702           }
703         }
704       break;
705     case MR_SUCCESS:
706       break;
707     default:
708       com_err(program_name, stat, " in AddFS");
709     }
710
711   if (stat == MR_SUCCESS && !strcasecmp(info[FS_L_TYPE], "HOMEDIR"))
712     {
713       static char *val[] = {"def_quota", NULL};
714       static char *def_quota = NULL;
715       char *argv[Q_QUOTA + 1];
716       struct mqelem *top = NULL;
717
718       if (!def_quota)
719         {
720           stat = do_mr_query("get_value", CountArgs(val), val,
721                              StoreInfo, &top);
722           if (stat != MR_SUCCESS)
723             com_err(program_name, stat, " getting default quota");
724           else
725             {
726               top = QueueTop(top);
727               def_quota = strdup(((char **)top->q_data)[0]);
728               FreeQueue(top);
729             }
730         }
731       if (def_quota)
732         {
733           sprintf(buf, "Give user %s a quota of %s on filesys %s (Y/N)",
734                   info[FS_NAME], def_quota, info[FS_NAME]);
735           if (YesNoQuestion(buf, 1) == TRUE)
736             {
737               argv[Q_NAME] = argv[Q_FILESYS] = info[FS_NAME];
738               if (!strcmp(info[FS_TYPE], "NFS"))
739                 argv[Q_TYPE] = "USER";
740               else
741                 argv[Q_TYPE] = "ANY";
742               argv[Q_QUOTA] = def_quota;
743               if ((stat = do_mr_query("add_quota", Q_QUOTA + 1, argv, NULL,
744                                       NULL)))
745                 com_err(program_name, stat, " while adding quota");
746             }
747         }
748     }
749   else if (stat == MR_SUCCESS)
750     {
751       if (YesNoQuestion("Assign a quota on this filesystem (Y/N)", 1) == TRUE)
752         {
753           parsed_argc = 1;
754           parsed_argv[0] = info[FS_NAME];
755           AddQuota(parsed_argc, parsed_argv);
756         }
757     }
758
759   FreeInfo(info);
760   return DM_NORMAL;
761 }
762
763 /*      Function Name: SortAfter
764  *      Description: choose a sortkey to cause an item to be added after
765  *              the count element in the queue
766  *      Arguments: queue of filesys names & sortkeys, queue count pointer
767  *      Returns: sort key to use.
768  */
769
770 char *SortAfter(struct mqelem *elem, int count)
771 {
772   char *prev, *next, prevnext, *key, keybuf[9];
773
774   /* first find the two keys we need to insert between */
775   prev = "A";
776   for (; count > 0; count--)
777     {
778       prev = ((char **)elem->q_data)[1];
779       if (elem->q_forw)
780         elem = elem->q_forw;
781       else
782         break;
783     }
784   if (count > 0)
785     next = "Z";
786   else
787     next = ((char **)elem->q_data)[1];
788
789   /* now copy the matching characters */
790   for (key = keybuf; *prev && *prev == *next; next++)
791     *key++ = *prev++;
792
793   /* and set the last character */
794   if (*prev == 0)
795     *prev = prevnext = 'A';
796   else
797     prevnext = prev[1];
798   if (prevnext == 0)
799     prevnext = 'A';
800   if (*next == 0)
801     *next = 'Z';
802   if (*next - *prev > 1)
803     *key++ = (*next + *prev) / 2;
804   else
805     {
806       *key++ = *prev;
807       *key++ = (prevnext + 'Z') / 2;
808     }
809   *key = 0;
810   return strdup(keybuf);
811 }
812
813 /*      Function Name: AddFSToGroup
814  *      Description: add a filesystem to an FS group
815  *      Arguments: arc, argv - name of group in argv[1], filesys in argv[2].
816  *      Returns: DM_NORMAL.
817  */
818
819 int AddFSToGroup(int argc, char **argv)
820 {
821   int stat, count;
822   struct mqelem *elem = NULL;
823   char buf[BUFSIZ], *args[5], *bufp;
824
825   if ((stat = do_mr_query("get_fsgroup_members", 1, argv + 1, StoreInfo,
826                           &elem)))
827     {
828       if (stat != MR_NO_MATCH)
829         com_err(program_name, stat, " in AddFSToGroup");
830     }
831   if (elem == NULL)
832     {
833       args[0] = argv[1];
834       args[1] = argv[2];
835       args[2] = "M";
836       stat = do_mr_query("add_filesys_to_fsgroup", 3, args, NULL, NULL);
837       if (stat)
838         com_err(program_name, stat, " in AddFSToGroup");
839       return DM_NORMAL;
840     }
841   elem = QueueTop(elem);
842   fsgCount = 1;
843   Loop(elem, PrintFSGMembers);
844   sprintf(buf, "%d", QueueCount(elem));
845   bufp = strdup(buf);
846   if (GetValueFromUser("Enter number of filesystem it should follow "
847                        "(0 to make it first):", &bufp) == SUB_ERROR)
848     return DM_NORMAL;
849   count = atoi(bufp);
850   free(bufp);
851   args[2] = SortAfter(elem, count);
852
853   FreeQueue(QueueTop(elem));
854   args[0] = argv[1];
855   args[1] = argv[2];
856   stat = do_mr_query("add_filesys_to_fsgroup", 3, args, NULL, NULL);
857   if (stat == MR_EXISTS)
858     {
859       Put_message("That filesystem is already a member of the group.");
860       Put_message("Use the order command if you want to change the "
861                   "sorting order.");
862     }
863   else if (stat)
864     com_err(program_name, stat, " in AddFSToGroup");
865   return DM_NORMAL;
866 }
867
868
869 /*      Function Name: RemoveFSFromGroup
870  *      Description: delete a filesystem from an FS group
871  *      Arguments: arc, argv - name of group in argv[1].
872  *      Returns: DM_NORMAL.
873  */
874
875 int RemoveFSFromGroup(int argc, char **argv)
876 {
877   int stat;
878   char buf[BUFSIZ];
879
880   sprintf(buf, "Delete filesystem %s from FS group %s", argv[2], argv[1]);
881   if (!Confirm(buf))
882     return DM_NORMAL;
883   if ((stat = do_mr_query("remove_filesys_from_fsgroup", 2, argv + 1,
884                           NULL, NULL)))
885     com_err(program_name, stat, ", not removed.");
886   return DM_NORMAL;
887 }
888
889 /*      Function Name: ChangeFSGroupOrder
890  *      Description: change the sortkey on a filesys in an FSgroup
891  *      Arguments: arc, argv - name of group in argv[1].
892  *      Returns: DM_NORMAL.
893  */
894
895 int ChangeFSGroupOrder(int argc, char **argv)
896 {
897   int stat, src, dst, i;
898   struct mqelem *elem = NULL, *top, *tmpelem;
899   char buf[BUFSIZ], *bufp, *args[3];
900
901   if ((stat = do_mr_query("get_fsgroup_members", 1, argv + 1, StoreInfo,
902                           &elem)))
903     {
904       if (stat == MR_NO_MATCH)
905         {
906           sprintf(buf,
907                   "Ether %s is not a filesystem group or it has no members",
908                   argv[1]);
909           Put_message(buf);
910         }
911       else
912         com_err(program_name, stat, " in ChangeFSGroupOrder");
913       return DM_NORMAL;
914     }
915   top = QueueTop(elem);
916   fsgCount = 1;
917   Loop(top, PrintFSGMembers);
918   while (1)
919     {
920       bufp = strdup("1");
921       if (GetValueFromUser("Enter number of the filesystem to move:",
922                            &bufp) == SUB_ERROR)
923         return DM_NORMAL;
924       src = atoi(bufp);
925       free(bufp);
926       if (src < 0)
927         {
928           Put_message("You must enter a positive number (or 0 to abort).");
929           continue;
930         }
931       else if (src == 0)
932         {
933           Put_message("Aborted.");
934           return DM_NORMAL;
935         }
936       for (elem = top, i = src; i-- > 1 && elem->q_forw; elem = elem->q_forw)
937         ;
938       if (i > 0)
939         {
940           Put_message("You entered a number that is too high");
941           continue;
942         }
943       break;
944     }
945   while (1)
946     {
947       bufp = strdup("0");
948       if (GetValueFromUser("Enter number of filesystem it should follow "
949                            "(0 to make it first):", &bufp) == SUB_ERROR)
950         return DM_NORMAL;
951       dst = atoi(bufp);
952       free(bufp);
953       if (src == dst || src == dst + 1)
954         {
955           Put_message("That has no effect on the sorting order!");
956           return DM_NORMAL;
957         }
958       if (dst < 0)
959         {
960           Put_message("You must enter a non-negative number.");
961           continue;
962         }
963       for (tmpelem = top, i = dst; i-- > 1 && tmpelem->q_forw;
964            tmpelem = tmpelem->q_forw)
965         ;
966       if (i > 0)
967         {
968           Put_message("You entered a number that is too high");
969           continue;
970         }
971       break;
972     }
973   args[2] = SortAfter(top, dst);
974   args[0] = argv[1];
975   args[1] = ((char **)elem->q_data)[0];
976   if ((stat = do_mr_query("remove_filesys_from_fsgroup", 2, args,
977                           NULL, NULL)))
978     {
979       com_err(program_name, stat, " in ChangeFSGroupOrder");
980       return DM_NORMAL;
981     }
982   if ((stat = do_mr_query("add_filesys_to_fsgroup", 3, args,
983                              NULL, NULL)))
984     com_err(program_name, stat, " in ChangeFSGroupOrder");
985   return DM_NORMAL;
986 }
987
988
989 /* -------------- Top Level Menu ---------------- */
990
991 /*      Function Name: GetFSAlias
992  *      Description: Gets the value for a Filesystem Alias.
993  *      Arguments: argc, argv - name of alias in argv[1].
994  *      Returns: DM_NORMAL.
995  *      NOTES: There should only be one filesystem per alias, thus
996  *             this will work correctly.
997  */
998
999 int GetFSAlias(int argc, char **argv)
1000 {
1001   struct mqelem *top;
1002
1003   top = GetFSInfo(ALIAS, argv[1]);
1004   Put_message(" ");             /* blank line. */
1005   Loop(top, (void (*)(char **))PrintFSAlias);
1006   FreeQueue(top);
1007   return DM_NORMAL;
1008 }
1009
1010 /*      Function Name: CreateFSAlias
1011  *      Description: Create an alias name for a filesystem
1012  *      Arguments: argc, argv - name of alias in argv[1].
1013  *      Returns: DM_NORMAL.
1014  *      NOTES:  This requires (name, type, transl)  I get {name, translation}
1015  *              from the user.  I provide type, which is well-known.
1016  */
1017
1018 int CreateFSAlias(int argc, char **argv)
1019 {
1020   int stat;
1021   struct mqelem *elem, *top;
1022   char *args[MAX_ARGS_SIZE], buf[BUFSIZ], **info;
1023
1024   elem = NULL;
1025
1026   if (!ValidName(argv[1]))
1027     return DM_NORMAL;
1028
1029   args[ALIAS_NAME] = strdup(argv[1]);
1030   args[ALIAS_TYPE] = strdup(FS_ALIAS_TYPE);
1031   args[ALIAS_TRANS] = strdup("*");
1032
1033   /*
1034    * Check to see if this alias already exists in the database, if so then
1035    * print out values, free memory used and then exit.
1036    */
1037
1038   if (!(stat = do_mr_query("get_alias", 3, args, StoreInfo, &elem)))
1039     {
1040       top = elem = QueueTop(elem);
1041       while (elem)
1042         {
1043           info = elem->q_data;
1044           sprintf(buf, "The alias: %s currently describes the filesystem %s",
1045                   info[ALIAS_NAME], info[ALIAS_TRANS]);
1046           Put_message(buf);
1047           elem = elem->q_forw;
1048         }
1049       FreeQueue(top);
1050       return DM_NORMAL;
1051     }
1052   else if (stat != MR_NO_MATCH)
1053     {
1054       com_err(program_name, stat, " in CreateFSAlias.");
1055       return DM_NORMAL;
1056     }
1057
1058   args[ALIAS_TRANS] = strdup("");
1059   args[ALIAS_END] = NULL;
1060   if (GetValueFromUser("Which filesystem will this alias point to?",
1061                        &args[ALIAS_TRANS]) == SUB_ERROR)
1062     return DM_NORMAL;
1063
1064   if ((stat = do_mr_query("add_alias", 3, args, NULL, NULL)))
1065     com_err(program_name, stat, " in CreateFSAlias.");
1066
1067   FreeInfo(args);
1068   return DM_NORMAL;
1069 }
1070
1071 /*      Function Name: RealDeleteFSAlias
1072  *      Description: Does the real deletion work.
1073  *      Arguments: info - array of char *'s containing all useful info.
1074  *                 one_item - a Boolean that is true if only one item
1075  *                              in queue that dumped us here.
1076  *      Returns: none.
1077  */
1078
1079 void RealDeleteFSAlias(char **info, Bool one_item)
1080 {
1081   int stat;
1082   char temp_buf[BUFSIZ];
1083
1084   /*
1085    * Deletions are  performed if the user hits 'y' on a list of multiple
1086    * filesystem, or if the user confirms on a unique alias.
1087    */
1088   sprintf(temp_buf,
1089           "Are you sure that you want to delete the filesystem alias %s",
1090           info[ALIAS_NAME]);
1091   if (!one_item || Confirm(temp_buf))
1092     {
1093       if ((stat = do_mr_query("delete_alias", CountArgs(info),
1094                               info, NULL, NULL)))
1095         com_err(program_name, stat, " filesystem alias not deleted.");
1096       else
1097         Put_message("Filesystem alias deleted.");
1098     }
1099   else
1100     Put_message("Filesystem alias not deleted.");
1101 }
1102
1103 /*      Function Name: DeleteFSAlias
1104  *      Description: Delete an alias name for a filesystem
1105  *      Arguments: argc, argv - name of alias in argv[1].
1106  *      Returns: DM_NORMAL.
1107  *      NOTES:  This requires (name, type, transl)  I get {name, translation}
1108  *              from the user.  I provide type, which is well-known.
1109  */
1110
1111 int DeleteFSAlias(int argc, char **argv)
1112 {
1113   struct mqelem *elem = GetFSInfo(ALIAS, argv[1]);
1114   QueryLoop(elem, PrintFSAlias, RealDeleteFSAlias,
1115             "Delete the Filesystem Alias");
1116   FreeQueue(elem);
1117   return DM_NORMAL;
1118 }
1119
1120 /*      Function Name: AttachHelp
1121  *      Description: Print help info on attachmaint.
1122  *      Arguments: none
1123  *      Returns: DM_NORMAL.
1124  */
1125
1126 int AttachHelp(void)
1127 {
1128   static char *message[] = {
1129     "These are the options:",
1130     "",
1131     "get - get information about a filesystem.",
1132     "add - add a new filesystem to the data base.",
1133     "update - update the information in the database on a filesystem.",
1134     "delete - delete a filesystem from the database.",
1135     "check - check information about association of a name and a filesys.",
1136     "alias - associate a name with a filesystem.",
1137     "unalias - disassociate a name with a filesystem.",
1138     "verbose - toggle the request for delete confirmation.",
1139     NULL,
1140   };
1141
1142   return PrintHelp(message);
1143 }
1144
1145 /*      Function Name: FSGroupHelp
1146  *      Description: Print help info on fsgroups.
1147  *      Arguments: none
1148  *      Returns: DM_NORMAL.
1149  */
1150
1151 int FSGroupHelp(int argc, char **argv)
1152 {
1153   static char *message[] = {
1154     "A filesystem group is a named sorted list of filesystems.",
1155     "",
1156     "To create, modify, or delete a group itself, use the menu above",
1157     "  this one, and manipulate a filesystem of type FSGROUP.",
1158     "Options here are:",
1159     "  get - get info about a group and show its members",
1160     "  add - add a new member to a group.",
1161     "  remove - remove a member from a group.",
1162     "  order - change the sorting order of a group.",
1163     NULL
1164   };
1165
1166   return PrintHelp(message);
1167 }
This page took 0.134114 seconds and 5 git commands to generate.