/* * Copyright (c) 1991, 1992, 1993 by the University of Southern California * * For copying and distribution information, please see the file * */ #include #include #define VERBOSE /* * newvs - Create new virtual systems * * Verbosity flag: 0 - Prompt for input * 1 - Explain what is needed as input * 2 - List each action taken * 3 - Stop before each step * 4 - Stop before each step, and explain the action */ /* make more efficinet by caching some of the dir pointers */ #include #include #include #include #define max(x,y) (((x) > (y)) ? x : y) char *prog; int pfs_debug = 0; void main(argc,argv) int argc; char *argv[]; { char *progname = argv[0]; char *cur_arg; char vshost[100]; char vsname[100]; char home[100]; char vsdescfile[100]; char buf[100]; /* used as temporary. */ char owner[1000]; FILE *vsdesc; char vsnamepath[100]; char vsabsname[100]; char vs_root[MAX_VPATH]; char vs_subdir[MAX_VPATH]; char vs_temp[MAX_VPATH]; char cont[100]; VDIR_ST dir_st; VDIR dir= &dir_st; VLINK pl; /* Prototype links */ VLINK vl; ACL_ST oacl_st; /* Owner ACL */ ACL oacl = &oacl_st; /* Owner ACL pointer */ int empty = 0; #ifdef VERBOSE int verbose = 2; #endif VERBOSE char *period; int nchr; int retval; prog = argv[0]; p_initialize("ufP", 0, (struct p_initialize_st *) NULL); vdir_init(dir); *vshost = '\0'; *vsname = '\0'; *home = '\0'; *owner = '\0'; *vsdescfile = '\0'; argc--;argv++; while (argc > 0 && **argv == '-') { cur_arg = argv[0]+1; /* If a - by itself, then no more arguments */ if(!*cur_arg) { argc--, argv++; goto scandone; } while (*cur_arg) { switch (*cur_arg++) { case 'D': /* Debug level */ pfs_debug = 1; /* Default debug level */ sscanf(cur_arg,"%d",&pfs_debug); cur_arg += strspn(cur_arg,"0123456789"); break; case 'e': /* Empty */ empty++; break; #ifdef VERBOSE case 'v': /* Verbosity */ case 'V': /* Verbosity */ verbose = 1; /* Default debug level */ sscanf(cur_arg,"%d",&verbose); cur_arg += strspn(cur_arg,"0123456789"); break; #endif VERBOSE default: fprintf(stderr, "Usage: newvs [-D[#]] [-e] [-v[#]] [host [name [home [owner [descfile]]]]]\n"); exit(1); } } argc--, argv++; } scandone: if (argc > 5) { fprintf(stderr, "Usage: newvs [host [name [home [owner [descfile]]]]]\n"); exit(1); } /* check for args in order host, vsname, homedir */ /* If still some left, print error message */ if (argc > 0) strcpy(vshost,argv[1]); if (argc > 1) strcpy(vsname,argv[2]); if (argc > 2) strcpy(home,argv[3]); if (argc > 3) strcpy(owner,argv[4]); if (argc > 4) strcpy(vsdescfile,argv[5]); #ifdef VERBOSE if(verbose >= 2) printf("\nSetting virtual system to %s...",P_MASTER_VS); #endif VERBOSE sprintf(vs_temp,"/VIRTUAL-SYSTEMS/%s",P_MASTER_VS); if(pget_wdhost()) vfsetenv("","",vs_temp); else vfsetenv("","",P_MASTER_VS); #ifdef VERBOSE if(verbose >= 2) printf("Done.\n"); if(verbose >= 2) printf("Reading list of storage sites from /pfs_storage..."); #endif VERBOSE retval = rd_vdir("/pfs_storage",0,dir,0); if(retval) { perrmesg("Can't read /pfs_storage: ", retval, NULL); exit(1); } #ifdef VERBOSE if(verbose >= 2) printf("Done.\n"); if((verbose >= 1) && (*vshost == '\0')) { printf("\nHost is the name of the host on which the root\n"); printf("of the new virtual system is to be stored. For a\n"); printf("list of choices type a question mark.\n\n"); } #endif VERBOSE prompthost: if(*vshost == '\0') { printf("Host: "); if(gets(vshost) == NULL) exit(1); } if((*vshost == '\0') || (strcmp(vshost,"?") == 0)) { vl = dir->links; printf("\n"); while(vl) { printf(" %s\n",vl->name); vl = vl->next; } printf("\n"); *vshost = '\0'; goto prompthost; } vl = dir->links; while(vl) { nchr = 0; period = strchr(vl->name,'.'); if(period) nchr = period - vl->name; nchr = max(strlen(vshost), nchr); if(strcncmp(vl->name,vshost,nchr) == 0) break; vl = vl->next; } if(vl == NULL) { printf("Not found.\n"); *vshost = '\0'; goto prompthost; } sprintf(vs_root,"/pfs_storage/%s/local_vsystems/",vl->name); #ifdef VERBOSE if((verbose >= 1) && (*vsname == '\0')) { printf("\nName is the default name by which others will refer\n"); printf("to the new virtual system. If this is your personal\n"); printf("virtual system, it should be your username. If this\n"); printf("virtual system is for a project, a name describing the\n"); printf("project is appropriate. Additional names may be\n"); printf("added at a later time.\n\n"); } #endif VERBOSE promptvsname: if(*vsname == '\0') { printf("Name: "); if(gets(vsname) == NULL) exit(1); } if(*vsname == '\0') goto promptvsname; sprintf(vsnamepath,"/%s/VIRTUAL-SYSTEMS/%s",P_PROTOTYPE_VS,vsname); retval = rd_vdir(vsnamepath,0,dir,RVD_DFILE_ONLY); if((retval == 0) && dir->links) { #ifdef VERBOSE if(verbose >= 1) { printf("\nThe name you have chosen is already in use.\n"); printf("This means that the name is already being used\n"); printf("by local users to refer to a different virtual\n"); printf("system. Please choose a different name. You\n"); printf("may add an additional name at a later time, \n"); printf("including one that is already in use.\n\n"); } else #endif VERBOSE printf("Name already in use, please choose another.\n"); *vsname = '\0'; goto promptvsname; } strcat(vs_root,vsname); #ifdef VERBOSE if((verbose >= 1) && (*home == '\0')) { printf("\nHome is the name of the home directory relative\n"); printf("to the root of the new virtual system. If this is\n"); printf("a personal virtual system, \"/vsname\" where vsname is\n"); printf("the name of the virtual system is suggested. If the\n"); printf("directory is top level and does not already exist,\n"); printf("then it will be automatically created.\n\n"); } #endif VERBOSE prompthome: if(*home == '\0') { printf("Home Directory: "); if(gets(home) == NULL) exit(1); } if(*home == '\0') goto prompthome; /* Need better checking for valid names */ if(*home != '/') { printf("Path must begin with a /.\n"); *home = '\0'; goto prompthome; } #ifdef VERBOSE if((verbose >= 1) && (*owner == '\0')) { printf("\nOwner is a list of users authorized to change\n"); printf("the new virtual system. The owner will be granted\n"); printf("full rights in the directories that are created.\n"); printf("The owner or owners will get an ACL entry of the type ASRTHOST.\n"); } #endif VERBOSE promptowner: if(*owner == '\0') { printf("Owner: "); if(gets(owner) == NULL) exit(1); } if(*owner == '\0') goto promptowner; /* Start constructing systems */ #ifdef VERBOSE if(verbose == 3) printf("\nAbout to create root of virtual system.\n[Type to continue]"); if(verbose >= 4) { printf("\nAbout to create the root of the virtual system.\n"); printf("This is accomplished by creating the directory:\n\n"); printf(" %s\n\n",vs_root); printf("relative to the root of the master virtual system.\n"); printf("[Type to continue]"); } if(verbose >= 3) { gets(cont); printf("\n"); } if(verbose >= 2) printf("Creating %s...",vs_root); #endif VERBOSE retval = mk_vdir(vs_root,MKVD_LPRIV); if(retval == DIRSRV_NOT_AUTHORIZED) { fflush(stdout); perrmesg("\nUnable to create virtual system: ", retval, NULL); exit(1); } if(retval && (retval != DIRSRV_ALREADY_EXISTS)) { perrmesg("Error creating root: ", retval, NULL); exit(1); } #ifdef VERBOSE if(verbose >= 2) printf("Done.\n"); if(verbose >= 2) printf("Setting ACL..."); #endif VERBOSE retval = rd_vdir(vs_root,0,dir,RVD_DFILE_ONLY); oacl->acetype = ACL_ASRTHOST; oacl->atype = ""; oacl->rights = "ALRMDI"; oacl->principals = qtokenize(owner); if(!retval) retval = modify_acl(dir->links,NULL,oacl,EACL_DIRECTORY|EACL_ADD); if(retval) { perrmesg("Error setting ACL: ", retval, NULL); exit(1); } #ifdef VERBOSE if(verbose >= 2) printf("Done.\n"); if(verbose >= 2) printf("Reading /%s...",P_PROTOTYPE_VS); #endif VERBOSE sprintf(vs_temp,"/%s",P_PROTOTYPE_VS); retval = rd_vdir(vs_temp,0,dir,RVD_EXPAND); if(retval) { perrmesg("Error reading prototype: ", retval, NULL); exit(1); } #ifdef VERBOSE if(verbose >= 2) printf("Done.\n\n"); #endif VERBOSE if(empty) goto leave_empty; #ifdef VERBOSE if(verbose == 3) printf("About to setup subdirectories.\n[Type to continue]"); if(verbose >= 4) { printf("About to setup subdirectories. For each subdirectory in\n"); printf("/%s, a new subdirectory will be created in the new\n",P_PROTOTYPE_VS); printf("virtual system. The subdirectory from /%s will\n",P_PROTOTYPE_VS); printf("then be added as a union link. This creates a customizable\n"); printf("subdirectory whose contents track that of the master copy.\n"); printf("[Type to continue]"); } if(verbose >= 3) { if(gets(cont) == NULL) exit(1); printf("\n"); } #endif VERBOSE pl = dir->links; while(pl) { if(strcmp(pl->name,"VS-DESCRIPTION") != 0) { sprintf(vs_subdir,"%s/%s",vs_root,pl->name); #ifdef VERBOSE if(verbose >= 2) printf("Creating %s...",vs_subdir); #endif VERBOSE retval = mk_vdir(vs_subdir,MKVD_LPRIV); if(retval && (retval != DIRSRV_ALREADY_EXISTS)) { perrmesg("Error creating subdir: ", retval, NULL); exit(1); } #ifdef VERBOSE if(verbose >= 2) printf("Adding union link to master copy..."); #endif VERBOSE retval = add_vlink(vs_subdir,"master",pl,AVL_UNION); if(retval && (retval != DIRSRV_ALREADY_EXISTS)) { perrmesg("Error adding union link: ", retval, NULL); exit(1); } #ifdef VERBOSE if(verbose >= 2) printf("Done.\n"); #endif VERBOSE } pl = pl->next; } leave_empty: if(strcmp(home,"/") == 0) goto no_home; sprintf(vs_subdir,"%s%s",vs_root,home); #ifdef VERBOSE if(verbose >= 3) printf("\nAbout to create home directory.\n[Type to continue]"); if(verbose >= 3) { if(gets(cont) == NULL) exit(1); printf("\n"); } if(verbose >= 2) printf("Creating %s...",vs_subdir); #endif VERBOSE retval = mk_vdir(vs_subdir,MKVD_LPRIV); if(retval) perrmesg("Home directory not created: ", retval, NULL); #ifdef VERBOSE if(verbose >= 2) printf("Done %s.\n",vs_subdir); #endif VERBOSE no_home: #ifdef VERBOSE if(verbose == 3) printf("\nAbout to create VS-DESCRIPTION.\n[Type to continue]"); if(verbose >= 4) { printf("\nAbout to create VS-DESCRIPTION. This will contain information\n"); printf("about the root and home directory of the virtual system.\n"); printf("[Type to continue]"); } if(verbose >= 3) { if(gets(cont) == NULL) exit(1); printf("\n"); } if(verbose >= 2) printf("Creating /VS-DESCRIPTION..."); #endif VERBOSE /* Create the VS-DESCRIPTION */ sprintf(vs_subdir,"%s/VS-DESCRIPTION",vs_root); retval = mk_vdir(vs_subdir,MKVD_LPRIV); if(retval && (retval != DIRSRV_ALREADY_EXISTS)) { perrmesg("Error creating subdir: ", retval, NULL); exit(1); } /* create ROOT link */ sprintf(vs_subdir,"%s/VS-DESCRIPTION",vs_root); retval = rd_vdir(vs_root,0,dir,RVD_DFILE_ONLY); #ifdef VERBOSE if(verbose >= 2) printf("Done.\nAdding ROOT..."); #endif VERBOSE retval = add_vlink(vs_subdir,"ROOT",dir->links,0); if(retval) perrmesg("Error adding link to VS-DESCRIPTION: ", retval, NULL); #ifdef VERBOSE if(verbose >= 2) printf("Done.\nAdding HOME..."); #endif VERBOSE vl = vlalloc(); /* LEAKS */ vl->name = stcopy("HOME"); vl->target = stcopyr("SYMBOLIC", vl->target); vl->hosttype = stcopyr("VIRTUAL-SYSTEM", vl->hosttype); vl->hsoname = stcopyr(home, vl->hsoname); /* Should LOCAL-VSLIST really be in prototype, or should it */ /* be in master. I think in prototype, but should it */ /* somehow encoded in HOME */ /* Clean up this code so we don't use dir->links */ sprintf(vs_temp,"/%s/VS-DESCRIPTION/LOCAL-VSLIST", P_PROTOTYPE_VS); vllfree(dir->links); dir->links = rd_slink(vs_temp); if(!dir->links) { fprintf(stderr,"Can't find prototype:/VS-DESCRIPTION/LOCAL-VSLIST\n"); } /* hostname - need to figure it out in a better way */ sprintf(vsabsname,"%s/%s",dir->links->host,vsname); vl->host = stcopy(vsabsname); retval = add_vlink(vs_subdir,"HOME",vl,0); if(retval) perrmesg("Error adding VS-DESCRIPTION link: ", retval, NULL); #ifdef VERBOSE if(verbose >= 2) printf("Done.\n"); if(verbose == 3) printf("\nAbout to add VS-DESCRIPTION to local VS list.\n[Type to continue]"); if(verbose >= 4) { printf("\nThe description of the new virtual system has been created, \n"); printf("but it has not yet been inserted into the global namespace.\n"); printf("We do this by adding the description to the local VS list.\n"); printf("This provides the VS with a default local name, and automatically\n"); printf("gives it a longer global name as well. The global name is\n"); printf("The path from a well known point to to the local VS list, plus\n"); printf("the local name of the system.\n"); printf("[Type to continue]"); } if(verbose >= 3) { if(gets(cont) == NULL) exit(1); printf("\n"); } if(verbose >= 2) printf("Adding to local VS list..."); #endif VERBOSE /* add a directory pointer to /VIRTUAL-SYSTEMS/# */ /* This is done now through /prototype/VIRTUAL-SYSTEMS */ /* which is a pointer to the correct subdirectory */ /* It might be better to start from # and traverse the */ /* whole path, but it would be slower. Also should we */ /* start from prototype or master/VIRTUAL-SYSTEMS/#? */ /* create ROOT link */ sprintf(vs_subdir,"%s/VS-DESCRIPTION",vs_root); retval = rd_vdir(vs_subdir,0,dir,RVD_DFILE_ONLY); if(retval == 0) { sprintf(vs_temp,"/%s/VIRTUAL-SYSTEMS",P_PROTOTYPE_VS); retval = add_vlink(vs_temp,vsname,dir->links,0); } #ifdef VERBOSE if(verbose >= 2) printf("Done.\n"); #endif VERBOSE if(strcmp(vsdescfile,"-") == 0) goto nodesc; if((verbose >= 1) && (*vsdescfile == '\0')) { printf("\nDo you want to create a virtual system description file?\n"); printf("The virtual system description file can be read by\n"); printf("vfsetup to find the description for this virtual\n"); printf("It is not absolutely necessary, because the\n"); printf("description can also be found by name. If this is\n"); printf("your primary virtual system, then it is suggested that\n"); printf("you create a virtual system description file named\n"); printf("\"~/.virt-sys\". This file is read when vfsetup is\n"); printf("called without arguments.\n\n"); } promptdescf: if(*vsdescfile == '\0') { printf("Create a virtual system description file (y/n)? "); if(gets(vsdescfile) == NULL) exit(1); } if((*vsdescfile == 'n') || (*vsdescfile == 'N')) goto nodesc; if((*vsdescfile != 'y') && (*vsdescfile != 'Y')) { *vsdescfile = '\0'; goto promptdescf; } printf("Description file [~/.virt-sys]: "); if(gets(vsdescfile) == NULL) exit(1); if(*vsdescfile == '\0') { strcpy(vsdescfile,"~/.virt-sys"); } if (*vsdescfile == '~') { extern char *getenv(); strcpy(buf, getenv("HOME")); strcat(buf, vsdescfile + 1); strcpy(vsdescfile, buf); } if((vsdesc = fopen(vsdescfile,"w")) == NULL) { fprintf(stderr,"%s: Can't open system description file for write - %s; no description file written. All other changes still remain in effect.\n", progname,vsdescfile); goto nodesc; } /* Find VS-DESCRIPTION again */ sprintf(vs_subdir,"%s/VS-DESCRIPTION",vs_root); retval = rd_vdir(vs_subdir,0,dir,RVD_DFILE_ONLY); if(!retval) fprintf(vsdesc,"%s %s\n",dir->links->host,dir->links->hsoname); else fprintf(stderr,"%s: Can't find VS-DESCRIPTION\n", progname); fclose(vsdesc); nodesc: exit(0); }