00001
00002
00003
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
00051
00052
00053
00054
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) {};
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
00153 extern int getopt();
00154 extern char *optarg;
00155 extern int optind;
00156 int any = 0;
00157 int opt;
00158 int error = 0;
00159
00160
00161
00162
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
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
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
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
00381 if(setup) {
00382 for(cpp = argv+optind; *cpp; ++cpp) {
00383 insert(&pathlist,
00384 make_Cell((**cpp == '\0') ? null : *cpp));
00385 }
00386 }
00387
00388
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
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
00417
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
00440
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
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
00466 if(!pathlist) add_at_front(&pathlist,make_Cell("/bin"));
00467 }
00468
00469
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