dropit.c

Go to the documentation of this file.
00001 /* dropit.c, originated at Fermilab */
00002 
00003 /* Note: this program was deliberately written in a K&R style. */
00004 
00005 #include <stdio.h>
00006 #include <string.h>
00007 #ifndef __APPLE__
00008 #include <malloc.h>
00009 #endif
00010 #include <sys/types.h>
00011 #include <sys/stat.h>
00012 #include <stdlib.h>
00013 
00014 static const char *command = "<Unknown>";
00015 
00016 static char *safe = 0;
00017 
00018 struct Cell_s {
00019    struct Cell_s *next;
00020    char *value;
00021 };
00022 
00023 static struct Cell_s *pathlist = 0;
00024 
00025 static struct Cell_s *
00026 make_Cell(const char *str)
00027 {
00028    struct Cell_s *retval = (struct Cell_s *)malloc(sizeof(struct Cell_s));
00029    if(retval) {
00030       if(str) {
00031          char *value = (char *)malloc(strlen(str) + 1);
00032          if(value) {
00033             (void) strcpy(value,str);
00034             retval->next = 0;
00035             retval->value = value;
00036          } else {
00037             free(retval);
00038             retval = 0;
00039          }
00040       }
00041    }
00042    return retval;
00043 }
00044 
00045 static void
00046 destroy_Cell(
00047              struct Cell_s *cell)
00048 {
00049    /* 
00050     ** This used to not be ifdefed, and sometimes free-ed
00051     ** things that were not malloc-ed. (like the "." string,
00052     ** and argv[n], etc.
00053     ** besides, we free a bunch of stuff and then exit, so
00054     ** why waste the cygles? -- mengel
00055     */
00056 #ifdef slow_me_down_and_free_things_not_malloced
00057    if(cell) {
00058       if(cell->value) free(cell->value); 
00059       free(cell);
00060    }
00061 #else
00062    if (cell) {}; // avoid unused variable message.
00063 #endif
00064 }
00065 
00066 static void
00067 add_at_front(
00068              struct Cell_s **list, struct Cell_s *cell)
00069 {
00070    if(list && cell) {
00071       cell->next = *list;
00072       *list = cell;
00073    } else {
00074       printf("%s\n",safe);
00075       exit(1);
00076    }
00077 }
00078 
00079 static void
00080 add_at_back(
00081             struct Cell_s **list, struct Cell_s *cell)
00082 {
00083    if(list && cell) {
00084       struct Cell_s *previous, *current;
00085       for(previous = 0, current = *list;
00086           current;
00087           previous = current, current = current->next) {
00088       }
00089       if(previous) {
00090          previous->next = cell;
00091       } else {
00092          *list = cell;
00093       }
00094       cell->next = 0;
00095    } else {
00096       printf("%s\n",safe);
00097       exit(1);
00098    }
00099    
00100 }
00101 
00102 static int
00103 contains(char *field,char *test)
00104 {
00105    char *place;
00106    int len = strlen(test);
00107    
00108    if(len == 0) {
00109       return 1;
00110    }
00111    while( (place = strchr(field,test[0])) ) {
00112       if(strncmp(place,test,len) == 0) {
00113          return 1;
00114       }
00115       field = place + 1;
00116    }
00117    return 0;
00118 }
00119 
00120 static int
00121 anchored(char *field,char *test)
00122 {
00123    int len = strlen(test);
00124    if(len == 0) {
00125       return 1;
00126    }
00127    if (strncmp(field,test,len) == 0) {
00128       return 1;
00129    }
00130    return 0;
00131 }
00132 
00133 static int
00134 exact(char *field,char *test)
00135 {
00136    if(strcmp(field,test) == 0) {
00137       return 1;
00138    }
00139    return 0;
00140 }
00141 
00142 int main(int argc,char **argv)
00143 {
00144    extern char *getenv();
00145    int (*compare)() = 0;
00146    void (*insert)() = 0;
00147    const char *path = "";
00148    const char *odel = "";
00149    const char *null = "";
00150    char idel = 0;
00151    char **cpp;
00152    // char *temp;
00153    extern int getopt();
00154    extern char *optarg;
00155    extern int optind; // , opterr;
00156    int any = 0;
00157    int opt;
00158    int error = 0;
00159    // int length;
00160    // int Lodel;
00161    // extern int errno;
00162    // extern char *sys_errlis[];
00163    int Anchored = 0;
00164    int Exact = 0;
00165    int first = 0;
00166    int cshmode = 0;
00167    int setup = 0;
00168    int Safe = 0;
00169    int duplicates = 1;
00170    int protected = 0;
00171    int existance = 0;
00172    int Ddefault = 1;
00173    int Edefault = 1;
00174    int Pdefault = 1;
00175    int Sdefault = 1;
00176    int adefault = 1;
00177    int cdefault = 1;
00178    int edefault = 1;
00179    int fdefault = 1;
00180    int idefault = 1;
00181    int ndefault = 1;
00182    int odefault = 1;
00183    int pdefault = 1;
00184    int sdefault = 1;
00185    struct Cell_s *previous, *current;
00186    struct stat sb;
00187    
00188    if(argv && *argv) {
00189       char *cp = strrchr(argv[0],'/');
00190       command = cp ? (cp+1) : *argv;
00191    }
00192    
00193    while((opt = getopt(argc,argv,"i:d:n:p:aefsciDEPS?")) != -1) {
00194       switch(opt) {
00195          case 'D':
00196             duplicates = 0;
00197             if(Ddefault) Ddefault = 0; else error = 1;
00198             break;
00199          case 'E':
00200             existance = 1;
00201             if(Edefault) Edefault = 0; else error = 1;
00202             break;
00203          case 'P':
00204             protected = 1;
00205             if(Pdefault) Pdefault = 0; else error = 1;
00206             break;
00207          case 'S':
00208             Safe = 1;
00209             if(Sdefault) Sdefault = 0; else error = 1;
00210             break;
00211          case 'a':
00212             Anchored = 1;
00213             if(adefault) adefault = 0; else error = 1;
00214             break;
00215          case 'e':
00216             Exact = 1;
00217             if(edefault) edefault = 0; else error = 1;
00218             break;
00219          case 'f':
00220             first = 1;
00221             if(fdefault) fdefault = 0; else error = 1;
00222             break;
00223          case 'p':
00224             path = optarg;
00225             if(pdefault) pdefault = 0; else error = 1;
00226             break;
00227          case 'i':
00228             idel = optarg[0];
00229             if(idefault) idefault = 0; else error = 1;
00230             break;
00231          case 'd':
00232             odel = optarg;
00233             if(odefault) odefault = 0; else error = 1;
00234             break;
00235          case 'n':
00236             null = optarg;
00237             if(ndefault) ndefault = 0; else error = 1;
00238             break;
00239          case 's':
00240             setup = 1;
00241             if(sdefault) sdefault = 0; else error = 1;
00242             break;
00243          case 'c':
00244             cshmode = 1;
00245             if(cdefault) cdefault = 0; else error = 1;
00246             break;
00247          default:
00248             error = 1;
00249       }
00250    }
00251    
00252    if(cshmode) {
00253       if(idefault) idel = pdefault ? ':' : ' ';
00254       if(odefault) odel = " ";
00255    } else {
00256       if(idefault) idel = ':';
00257       if(odefault) odel = ":";
00258    }
00259    
00260    /* Create a `safe' path, preferably their current PATH */
00261    
00262    {   char *syspath = getenv("PATH");
00263       if(!syspath) syspath = "/bin:/sbin:/usr/bin:/usr/bin";
00264       
00265       if(strlen(odel) == 1) {
00266          safe = (char *)malloc(strlen(syspath)+1);
00267          if(safe) {
00268             char *cp;
00269             (void) strcpy(safe,syspath);
00270             for(cp = safe; *cp; ++cp) if(*cp == ':') *cp = odel[0];
00271          }
00272       } else {
00273          char *cp;
00274          int del = 0;
00275          for(cp = syspath; *cp; ++cp) if(*cp == ':') ++del;
00276          safe = (char *)malloc(strlen(syspath)+del*(strlen(odel)-1)+1);
00277          if(safe) {
00278             char byte[2];
00279             byte[1] = '\0';
00280             safe[0] = '\0';
00281             for(cp = syspath; *cp; ++cp) {
00282                byte[0] = *cp;
00283                if(*cp == ':') {
00284                   strcat(safe,odel);
00285                } else {
00286                   strcat(safe,byte);
00287                }
00288             }
00289          }
00290       }
00291       if(!safe) {
00292          if(strlen(odel) == 1) {
00293             if(odel[0] == ' ') {
00294                safe = "/bin /sbin /usr/bin /usr/bin";
00295             } else if(odel[0] == ':') {
00296                safe = "/bin:/sbin:/usr/bin:/usr/bin";
00297             } else {
00298                safe = "/bin";
00299             }
00300          } else {
00301             safe = "/bin";
00302          }
00303       }
00304    }
00305    
00306    /* After this point, `safe' must not be changed! */
00307    
00308    if(error) {
00309       fprintf(stderr,
00310               "%s: usage: %s [-[aefscDEPS]] ... [-i x] [-d x] [-p path] [string] ...\n",
00311               command,command);
00312       printf("%s\n",safe);
00313       exit(1);
00314    }
00315    if(pdefault) ndefault = 1;
00316    if(ndefault) null = ".";
00317    
00318    if(pdefault) {
00319       path = getenv("PATH");
00320       if(!path) {
00321          idel = ':';
00322          path = "/bin:/sbin:/usr/bin:/usr/bin";
00323       }
00324    }
00325    
00326    if(path[0]) {
00327       char *lcp, *rcp;
00328       char *copy = (char *)malloc(strlen(path)+1);
00329       if(copy) {
00330          (void) strcpy(copy,path);
00331       } else {
00332          fprintf(stderr,"No memory to copy path\n");
00333          printf("%s\n",safe);
00334          exit(1);
00335       }
00336       for(lcp = copy, rcp = lcp; *rcp; ++rcp) {
00337          if(*rcp == idel) {
00338             *rcp = '\0';
00339             if(*lcp) {
00340                add_at_back(&pathlist,make_Cell(lcp));
00341             } else {
00342                add_at_back(&pathlist,make_Cell(null));
00343             }
00344             lcp = rcp + 1;
00345          }
00346       }
00347       if(*lcp) {
00348          add_at_back(&pathlist,make_Cell(lcp));
00349       } else {
00350          add_at_back(&pathlist,make_Cell(null));
00351       }
00352       free(copy);
00353    }
00354    
00355    compare = (Exact ? exact : (Anchored ? anchored : contains));
00356    insert = (first ? add_at_front : add_at_back);
00357    
00358    /* Do removals */
00359    for(cpp = argv+optind; *cpp; ++cpp) {
00360       struct Cell_s *next;
00361       if(Safe) {
00362          if(**cpp == '\0') continue;
00363          if(strcmp(*cpp,"/bin") == 0) continue;
00364       }
00365       for(previous = 0, current = pathlist; current; current = next) {
00366          next = current->next;
00367          if(compare(current->value,*cpp)) {
00368             if(previous) {
00369                previous->next = current->next;
00370             } else {
00371                pathlist = current->next;
00372             }
00373             destroy_Cell(current);
00374          } else {
00375             previous = current;
00376          }
00377       }
00378    }
00379    
00380    /* Do insertations, if requested */
00381    if(setup) {
00382       for(cpp = argv+optind; *cpp; ++cpp) {
00383          insert(&pathlist,
00384                 make_Cell((**cpp == '\0') ? null : *cpp));
00385       }
00386    }
00387    
00388    /* Do insertations of system director(y)(ies), if requested */
00389    if(protected) {
00390       add_at_front(&pathlist,make_Cell("/usr/bin/X11"));
00391       add_at_front(&pathlist,make_Cell("/usr/etc"));
00392       add_at_front(&pathlist,make_Cell("/etc"));
00393       add_at_front(&pathlist,make_Cell("/usr/sbin"));
00394       add_at_front(&pathlist,make_Cell("/usr/bin"));
00395       add_at_front(&pathlist,make_Cell("/sbin"));
00396       add_at_front(&pathlist,make_Cell("/bin"));
00397       add_at_back(&pathlist,make_Cell("/usr/local/bin"));
00398    }
00399    
00400    /* Remove duplicates */
00401    if(Safe || protected || !duplicates) {
00402       for(current = pathlist; current; current = current -> next) {
00403          struct Cell_s *prev, *curr, *next;
00404          for(prev = current, curr = current->next; curr; curr = next) {
00405             next = curr->next;
00406             if(strcmp(current->value,curr->value) == 0) {
00407                prev->next = curr->next;
00408                destroy_Cell(curr);
00409             } else {
00410                prev = curr;
00411             }
00412          }
00413       }
00414    }
00415    
00416    /* Remove nonexistant file system objects or non-directories, */
00417    /* if requested */
00418    if(existance) {
00419       struct Cell_s *next;
00420       for(previous = 0, current = pathlist;
00421           current;
00422           current = current -> next) {
00423          next = current->next;
00424          sb.st_mode = -1;
00425          if(stat(current->value,&sb) ||
00426             (sb.st_mode & S_IFMT) != S_IFDIR) {
00427             if(previous) {
00428                previous->next = current->next;
00429             } else {
00430                pathlist = current->next;
00431             }
00432             destroy_Cell(current); 
00433          } else {
00434             previous = current;
00435          }
00436       }
00437    }
00438    
00439    /* Do insertations of minimal system director(y)(ies), */
00440    /* if requested and needed */
00441    if(Safe && !pathlist) {
00442       add_at_front(&pathlist,make_Cell("/usr/sbin"));
00443       add_at_front(&pathlist,make_Cell("/usr/bin"));
00444       add_at_front(&pathlist,make_Cell("/sbin"));
00445       add_at_front(&pathlist,make_Cell("/bin"));
00446       /* Remove nonexistant file system objects or non-directories */
00447       struct Cell_s *next;
00448       for(previous = 0, current = pathlist;
00449           current;
00450           current = current -> next) {
00451          next = current->next;
00452          sb.st_mode = -1;
00453          if(stat(current->value,&sb) ||
00454             (sb.st_mode & S_IFMT) != S_IFDIR) {
00455             if(previous) {
00456                previous->next = current->next;
00457             } else {
00458                pathlist = current->next;
00459             }
00460             destroy_Cell(current);
00461          } else {
00462             previous = current;
00463          }
00464       }
00465       /* Recheck */
00466       if(!pathlist) add_at_front(&pathlist,make_Cell("/bin"));
00467    }
00468    
00469    /* Generate the new PATH value */
00470    {
00471       struct Cell_s *next;
00472       for(current = pathlist; current; current = next) {
00473          next = current->next;
00474          if(any) printf("%s",odel); else any = 1;
00475          printf("%s",current->value);
00476          destroy_Cell(current);
00477       }
00478    }
00479    pathlist = 0;
00480    printf("\n");
00481    
00482    exit(0);
00483 }
00484 

Generated on Tue Jul 5 14:10:18 2011 for ROOT_528-00b_version by  doxygen 1.5.1