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