1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
#include "wily.h"
#include <pwd.h>
static char* gettilde(const char*s);
static void pathclean(char*path);
/*
* Expand 'orig' into 'dest', using 'expansion'.
* Expansion must take a char*, and return a static char*,
* i.e. one we don't have to free (and can't keep).
*/
static void
expand(char*dest, char*orig, char*(*expansion)(const char*)){
Path key;
char *val;
char *slash;
assert(orig[0]=='$' || orig[0]=='~');
strcpy(key,orig+1);
if( (slash=strchr(key,'/')) ) {
*slash = 0;
}
val = (*expansion)(key);
if(slash)
*slash = '/';
if(val){
sprintf(dest, "%s%s", val, slash? slash: "");
} else {
strcpy(dest, orig);
}
}
/* Convert a 'label' to a 'path'. Paths are always absolute. */
void
label2path(char*path, char*label) {
if(!label){
strcpy(path,wilydir);
return;
}
switch(label[0]) {
case '$': expand(path, label, getenv); break;
case '~': expand(path, label, gettilde); break;
case '/': strcpy(path, label); break;
default: sprintf(path, "%s%s", wilydir, label); break;
}
pathclean(path);
}
/*********************************************************
static functions
*********************************************************/
/* Clean up 'path' by removing components with '.' or '..' */
static void
pathclean(char*path){
/* todo */
}
/* Clean up 'label' by removing components with '.' or '..' */
void
labelclean(char*label){
Path copy_path;
char *path,*new_path;
char c;
/* Make a copy of the source path since we may need to modify it. */
strcpy(copy_path, label);
path = copy_path;
new_path = label;
/* leading component */
while (path[0] != '/' && path[0] != '\0') {
*new_path++ = *path++;
}
/* first slash */
if(path[0] == '/')
*new_path++ = *path++;
/* Expand each slash-separated pathname component. */
while (*path != '\0') {
switch(path[0]){
case '/':
path++;
continue;
case '.':
switch(path[1]){
case '\0':
case '/': /* Ignore ".". */
path++;
continue;
case '.':
if (path[2] == '\0' || path[2] == '/') {
path += 2;
/* Ignore ".." at root. */
if (new_path == label + 1)
continue;
/* Handle ".." by backing up. */
while ((--new_path)[-1] != '/')
;
/* todo - handle $h/.. */
continue;
}
}
default:
; /* pass */
}
/* Safely copy the next pathname component. */
do {
c = *new_path++ = *path++;
} while (c != '\0' && c != '/');
}
*new_path='\0';
}
static char*
gettilde(const char*s) {
struct passwd *pw;
pw = strlen(s) ? getpwnam(s) : getpwuid(getuid());
return pw ? pw->pw_dir : 0;
}
|