Ejemplo n.º 1
0
int binary_search_first(int now)
{
	int from=now+1,to=nreal,mid;
	if(now>=nreal)
	{
		return -1;
	}

	if(is_link(now,from,to)==0)
	{
		return -1;
	}
	while(from<to)
	{
		/*		fprintf(stderr,"%d %d %d\n",from,to,mid); */
		mid=(from+to)/2;
		if(is_link(now,from,mid))
		{
			to=mid;
		}
		else if(is_link(now,mid,mid+1))
		{
			return mid;
		}
		else if(is_link(now,mid+1,to))
		{
			from=mid+1;
		}
	}
	return from;
}
Ejemplo n.º 2
0
QIcon FileTreeItem::icon() const {
    if (m_icon.isNull()) {
        FileTreeItem * p_this = (FileTreeItem *)this;
        if (is_dir()) p_this->m_icon=IconProvider::instance()->dirIcon(m_encripted,is_link());
        else p_this->m_icon=IconProvider::instance()->fileIcon(name(),m_encripted,is_link());
    }

    return m_icon;
}
Ejemplo n.º 3
0
// check new private home directory (--private= option) - exit if it fails
void fs_check_private_dir(void) {
	// Expand the home directory
	char *tmp = expand_home(cfg.home_private, cfg.homedir);
	cfg.home_private = realpath(tmp, NULL);
	free(tmp);
	
	if (!cfg.home_private
	 || !is_dir(cfg.home_private)
	 || is_link(cfg.home_private)
	 || strstr(cfg.home_private, "..")) {
		exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: invalid private directory\n");
		exit(1);
	}

	// check home directory and chroot home directory have the same owner
	struct stat s2;
	int rv = stat(cfg.home_private, &s2);
	if (rv < 0) {
		exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: cannot find %s directory\n", cfg.home_private);
		exit(1);
	}

	struct stat s1;
	rv = stat(cfg.homedir, &s1);
	if (rv < 0) {
		exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: cannot find %s directory, full path name required\n", cfg.homedir);
		exit(1);
	}
	if (s1.st_uid != s2.st_uid) {
		printf("Error: the two home directories must have the same owner\n");
		exit(1);
	}
}
Ejemplo n.º 4
0
// return 0 if file not found, 1 if found
static int check_dir_or_file(const char *name) {
	assert(name);
	invalid_filename(name);
	
	struct stat s;
	char *fname;
	if (asprintf(&fname, "/etc/%s", name) == -1)
		errExit("asprintf");
	if (arg_debug)
		printf("Checking %s\n", fname);		
	if (stat(fname, &s) == -1) {
		if (arg_debug)
			printf("Warning: file %s not found.\n", fname);
		return 0;
	}
	
	// dir or regular file
	if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) {
		free(fname);
		return 1;
	}

	if (!is_link(fname)) {
		free(fname);
		return 1;
	}
	
	fprintf(stderr, "Error: invalid file type, %s.\n", fname);
	exit(1);
}
Ejemplo n.º 5
0
// grab a copy of cp command
void fs_build_cp_command(void) {
	struct stat s;
	fs_build_mnt_dir();
	if (stat(RUN_CP_COMMAND, &s)) {
		char* fname = realpath("/bin/cp", NULL);
		if (fname == NULL) {
			fprintf(stderr, "Error: /bin/cp not found\n");
			exit(1);
		}
		if (stat(fname, &s)) {
			fprintf(stderr, "Error: /bin/cp not found\n");
			exit(1);
		}
		if (is_link(fname)) {
			fprintf(stderr, "Error: invalid /bin/cp file\n");
			exit(1);
		}
		int rv = copy_file(fname, RUN_CP_COMMAND);
		if (rv) {
			fprintf(stderr, "Error: cannot access /bin/cp\n");
			exit(1);
		}
		/* coverity[toctou] */
		if (chown(RUN_CP_COMMAND, 0, 0))
			errExit("chown");
		if (chmod(RUN_CP_COMMAND, 0755))
			errExit("chmod");
			
		free(fname);
	}
}
Ejemplo n.º 6
0
static int store_xauthority(void) {
	// put a copy of .Xauthority in XAUTHORITY_FILE
	fs_build_mnt_dir();

	char *src;
	char *dest = RUN_XAUTHORITY_FILE;
	if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1)
		errExit("asprintf");
	
	struct stat s;
	if (stat(src, &s) == 0) {
		if (is_link(src)) {
			fprintf(stderr, "Error: invalid .Xauthority file\n");
			exit(1);
		}
			
		int rv = copy_file(src, dest);
		if (rv) {
			fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
			return 0;
		}
		return 1; // file copied
	}
	
	return 0;
}
Ejemplo n.º 7
0
void fs_dev_disable_sound(void) {
	unsigned i = 0;
	while (dev[i].dev_fname != NULL) {
		if (dev[i].type == DEV_SOUND)
			disable_file_or_dir(dev[i].dev_fname);
		i++;
	}

	// disable all jack sockets in /dev/shm
	glob_t globbuf;
	int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf);
	if (globerr)
		return;

	for (i = 0; i < globbuf.gl_pathc; i++) {
		char *path = globbuf.gl_pathv[i];
		assert(path);
		if (is_link(path)) {
			fwarning("skipping nosound for %s because it is a symbolic link\n", path);
			continue;
		}
		disable_file_or_dir(path);
	}
	globfree(&globbuf);
}
Ejemplo n.º 8
0
int				seek_step_line(char *line, t_map *map)
{
	if (map->step == 0)
	{
		if (is_nbr_ant(line))
			save_nbr_ant(ft_atoi(line), map);
		else
			return (0);
	}
	else if (map->step == 1)
	{
		if (is_room(line))
			save_room(line, map);
		else
			return (0);
	}
	else if (map->step == 2)
	{
		if (is_link(line))
			save_link(line, map);
		else
			return (0);
	}
	return (1);
}
Ejemplo n.º 9
0
static void check_dir_or_file(const char *name) {
    assert(name);
    struct stat s;
    char *fname;
    if (asprintf(&fname, "/etc/%s", name) == -1)
        errExit("asprintf");
    if (arg_debug)
        printf("Checking %s\n", fname);
    if (stat(fname, &s) == -1) {
        exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: file %s not found.\n", fname);
        exit(1);
    }

    // dir or regular file
    if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) {
        free(fname);
        return;
    }

    if (!is_link(fname)) {
        free(fname);
        return;
    }

    exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: invalid file type, %s.\n", fname);
    exit(1);
}
Ejemplo n.º 10
0
int			check_link(t_lem_env *env, char *s)
{
	int		i;
	int		j;
	int		k;
	int		a;

	env->r.nolink = 0;
	if (matrice_visit0(env, &i, &j, &k) == 0)
		return (ft_error(env, 1));
	a = -1;
	if (!is_link(s) || (a = check_link2(env, s, &i, &j)) != 0)
		return (ft_error(env, 2));
	while (++k < env->nbroom)
	{
		if ((a = ft_strcmp(env->room[k], &s[i + 1])) == 0)
			break ;
	}
	if (a != 0 || j == k)
		return (ft_error(env, 2));
	if (env->matrice[j][k] == 1)
		return (ft_error(env, 2));
	env->matrice[k][j] += 1;
	env->matrice[j][k] += 1;
	env->r.nbline += add_file(env, s);
	return (1);
}
Ejemplo n.º 11
0
// check new private home directory (--private= option) - exit if it fails
void fs_check_private_dir(void) {
    invalid_filename(cfg.home_private);

    // Expand the home directory
    char *tmp = expand_home(cfg.home_private, cfg.homedir);
    cfg.home_private = realpath(tmp, NULL);
    free(tmp);

    if (!cfg.home_private
            || !is_dir(cfg.home_private)
            || is_link(cfg.home_private)
            || strstr(cfg.home_private, "..")) {
        fprintf(stderr, "Error: invalid private directory\n");
        exit(1);
    }

    // check home directory and chroot home directory have the same owner
    struct stat s2;
    int rv = stat(cfg.home_private, &s2);
    if (rv < 0) {
        fprintf(stderr, "Error: cannot find %s directory\n", cfg.home_private);
        exit(1);
    }

    struct stat s1;
    rv = stat(cfg.homedir, &s1);
    if (rv < 0) {
        fprintf(stderr, "Error: cannot find %s directory, full path name required\n", cfg.homedir);
        exit(1);
    }
    if (s1.st_uid != s2.st_uid) {
        printf("Error: --private directory should be owned by the current user\n");
        exit(1);
    }
}
Ejemplo n.º 12
0
static void list(void) {
	DIR *dir = opendir("/usr/local/bin");
	if (!dir) {
		fprintf(stderr, "Error: cannot open /usr/local/bin directory\n");
		exit(1);
	}

	char *firejail_exec;
	if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1)
		errExit("asprintf");

	struct dirent *entry;
	while ((entry = readdir(dir)) != NULL) {
		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
			continue;
		
		char *fullname;
		if (asprintf(&fullname, "/usr/local/bin/%s", entry->d_name) == -1)
			errExit("asprintf");
			
		if (is_link(fullname)) {
			char* fname = realpath(fullname, NULL);
			if (fname) {
				if (strcmp(fname, firejail_exec) == 0)
					printf("%s\n", fullname);
				free(fname);
			}
		}
		free(fullname);
	}
			
	closedir(dir);
	free(firejail_exec);
}
Ejemplo n.º 13
0
// check new private home directory (--private= option) - exit if it fails
void fs_check_private_dir(void) {
	// if the directory starts with ~, expand the home directory
	if (*cfg.home_private == '~') {
		char *tmp;
		if (asprintf(&tmp, "%s%s", cfg.homedir, cfg.home_private + 1) == -1)
			errExit("asprintf");
		cfg.home_private = tmp;
	}
	
	if (!is_dir(cfg.home_private) || is_link(cfg.home_private) || strstr(cfg.home_private, "..")) {
		fprintf(stderr, "Error: invalid private directory\n");
		exit(1);
	}

	// check home directory and chroot home directory have the same owner
	struct stat s2;
	int rv = stat(cfg.home_private, &s2);
	if (rv < 0) {
		fprintf(stderr, "Error: cannot find %s directory\n", cfg.home_private);
		exit(1);
	}

	struct stat s1;
	rv = stat(cfg.homedir, &s1);
	if (rv < 0) {
		fprintf(stderr, "Error: cannot find %s directory, full path name required\n", cfg.homedir);
		exit(1);
	}
	if (s1.st_uid != s2.st_uid) {
		printf("Error: the two home directories must have the same owner\n");
		exit(1);
	}
}
Ejemplo n.º 14
0
static void check_dir_or_file(const char *name) {
	assert(name);
	struct stat s;
	char *fname;
	if (asprintf(&fname, "%s/%s", cfg.homedir, name) == -1)
		errExit("asprintf");
	if (arg_debug)
		printf("***************Checking %s\n", fname);		
	if (stat(fname, &s) == -1) {
		fprintf(stderr, "Error: file %s not found.\n", fname);
		exit(1);
	}
	
	// check uid
	uid_t uid = getuid();
	gid_t gid = getgid();
	if (s.st_uid != uid || s.st_gid != gid) {
		fprintf(stderr, "Error: only files or directories created by the current user are allowed.\n");
		exit(1);
	}

	// dir or regular file
	if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) {
		free(fname);
		return;
	}

	if (!is_link(fname)) {
		free(fname);
		return;
	}
	
	fprintf(stderr, "Error: invalid file type, %s.\n", fname);
	exit(1);
}
Ejemplo n.º 15
0
static int store_asoundrc(void) {
	char *src;
	char *dest = RUN_ASOUNDRC_FILE;
	if (asprintf(&src, "%s/.asoundrc", cfg.homedir) == -1)
		errExit("asprintf");
	
	struct stat s;
	if (stat(src, &s) == 0) {
		if (is_link(src)) {
			// make sure the real path of the file is inside the home directory
			/* coverity[toctou] */
			char* rp = realpath(src, NULL);
			if (!rp) {
				fprintf(stderr, "Error: Cannot access %s\n", src);
				exit(1);
			}
			if (strncmp(rp, cfg.homedir, strlen(cfg.homedir)) != 0) {
				fprintf(stderr, "Error: .asoundrc is a symbolic link pointing to a file outside home directory\n");
				exit(1);
			}
			free(rp);
		}

		int rv = copy_file(src, dest, -1, -1, -0644);
		if (rv) {
			fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n");
			return 0;
		}
		return 1; // file copied
	}
	
	return 0;
}
Ejemplo n.º 16
0
int main(int argc, char **argv) {
	if (argc < 2) {
		fprintf(stderr, "Error: please provide a filename to store the program output\n");
		usage();
		exit(1);
	}
	char *fname = argv[1];


	// do not accept directories, links, and files with ".."
	if (strstr(fname, "..") || is_link(fname) || is_dir(fname)) {
		fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n");
		exit(1);
	}
	
	struct stat s;
	if (stat(fname, &s) == 0) {
		// check permissions
		if (s.st_uid != getuid() || s.st_gid != getgid()) {
			fprintf(stderr, "Error: the output file needs to be owned by the current user.\n");
			exit(1);
		}
		
		// check hard links
		if (s.st_nlink != 1) {
			fprintf(stderr, "Error: no hard links allowed.\n");
			exit(1);
		}
	}

	// check if we can append to this file
	/* coverity[toctou] */
	FILE *fp = fopen(fname, "a");
	if (!fp) {
		fprintf(stderr, "Error: cannot open output file %s\n", fname);
		exit(1);
	}
	fclose(fp);


	// preserve the last log file
	log_rotate(fname);

	setvbuf (stdout, NULL, _IONBF, 0);
	while(1) {
		int n = read(0, buf, sizeof(buf));
		if (n < 0 && errno == EINTR)
			continue;
		if (n <= 0)
			break;
		
		fwrite(buf, n, 1, stdout);
		log_write(buf, n, fname);
	}
	
	log_close();
	return 0;
}
Ejemplo n.º 17
0
void check_netfilter_file(const char *fname) {
    EUID_ASSERT();
    invalid_filename(fname);

    if (is_dir(fname) || is_link(fname) || strstr(fname, "..") || access(fname, R_OK )) {
        fprintf(stderr, "Error: invalid network filter file %s\n", fname);
        exit(1);
    }
}
Ejemplo n.º 18
0
linktyp *predlink(linktyp *lp)
/* Returnerar pekare till länken före  */
{
   linktyp *ep;

   if ( is_link(lp->befo) )
      ep = lp->befo;
   else
      ep = NULL;
   return ep;
}
Ejemplo n.º 19
0
t_state			get_link(t_lem *p, char *str)
{
	if (is_link(str) == 1)
	{
		fill_link(p, str);
		return (LINK);
	}
	else if (is_command(str) == 1)
		return (LINK);
	return (END);
}
Ejemplo n.º 20
0
linktyp *succlink(linktyp *lp)
/* Returnerar pekare till länken efter */
{
   linktyp *ep;

   if ( is_link(lp->next) )
      ep = lp->next;
   else
      ep = NULL;
   return ep;
}
Ejemplo n.º 21
0
void check_netfilter_file(const char *fname) {
	if (is_dir(fname) || is_link(fname) || strstr(fname, "..")) {
		exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: invalid network filter file\n");
		exit(1);
	}

	// access call checks as real UID/GID, not as effective UID/GID
	if (access(fname, R_OK)) {
		exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: cannot access network filter file\n");
		exit(1);
	}
}
Ejemplo n.º 22
0
void fs_var_tmp(void) {

	if (!is_link("/var/tmp")) {
		if (arg_debug)
			printf("Mounting tmpfs on /var/tmp\n");
		if (mount("tmpfs", "/var/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC,  "mode=777,gid=0") < 0)
			errExit("mounting /var/tmp");
	}
	else {
		fprintf(stderr, "Warning: /var/tmp not mounted\n");
		dbg_test_dir("/var/tmp");
	}
}
Ejemplo n.º 23
0
void dbg_test_dir(const char *dir) {
	if (arg_debug) {
		if (is_dir(dir))
			printf("%s is a directory\n", dir);
		if (is_link(dir)) {
			char *lnk = realpath(dir, NULL);
			if (lnk) {
				printf("%s is a symbolic link to %s\n", dir, lnk);
				free(lnk);
			}
		}
	}
}
Ejemplo n.º 24
0
static void check_dir_or_file(const char *name) {
	assert(name);
	struct stat s;
	
	invalid_filename(name);
	
	
	char *fname = expand_home(name, cfg.homedir);
	if (!fname) {
		fprintf(stderr, "Error: file %s not found.\n", name);
		exit(1);
	}
	if (fname[0] != '/') {
		// If it doesn't start with '/', it must be relative to homedir
		char* tmp;
		if (asprintf(&tmp, "%s/%s", cfg.homedir, fname) == -1)
			errExit("asprintf");
		free(fname);
		fname = tmp;
	}
	if (arg_debug)
		printf("Checking %s\n", fname);		
	if (stat(fname, &s) == -1) {
		fprintf(stderr, "Error: file %s not found.\n", fname);
		exit(1);
	}
	
	// check uid
	uid_t uid = getuid();
	gid_t gid = getgid();
	if (s.st_uid != uid || s.st_gid != gid) {
		fprintf(stderr, "Error: only files or directories created by the current user are allowed.\n");
		exit(1);
	}

	// dir or regular file
	if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) {
		free(fname);
		return;
	}

	if (!is_link(fname)) {
		free(fname);
		return;
	}
	
	fprintf(stderr, "Error: invalid file type, %s.\n", fname);
	exit(1);
}
Ejemplo n.º 25
0
// return 1 if found, 0 if not found
static char *check_dir_or_file(const char *name) {
	assert(name);
	invalid_filename(name);
	
	struct stat s;
	char *fname = NULL;
	
	int i = 0;
	while (paths[i]) {
		if (asprintf(&fname, "%s/%s", paths[i], name) == -1)
			errExit("asprintf");
		if (arg_debug)
			printf("Checking %s/%s\n", paths[i], name);		
		if (stat(fname, &s) == 0 && !S_ISDIR(s.st_mode)) { // do not allow directories
			// check symlink to firejail executable in /usr/local/bin
			if (strcmp(paths[i], "/usr/local/bin") == 0 && is_link(fname)) {
				char *actual_path = realpath(fname, NULL);
				if (actual_path) {
					char *ptr = strstr(actual_path, "/firejail");
					if (ptr && strlen(ptr) == strlen("/firejail")) {
						if (arg_debug)
							printf("firejail exec symlink detected\n");
						free(actual_path);
						free(fname);
						fname = NULL;
						i++;
						continue;
					}
					free(actual_path);
				}
				
			}		
			break; // file found
		}
		
		free(fname);
		fname = NULL;
		i++;
	}

	if (!fname) {
		if (arg_debug)
			fprintf(stderr, "Warning: file %s not found\n", name);
		return NULL;
	}
	
	free(fname);
	return paths[i];
}
Ejemplo n.º 26
0
int			check_room(t_lem_env *env, char *s)
{
	if (is_link(s) && env->fonction[env->r.state + 1](env, s))
		return (ft_add_state(env));
	if (ft_strcmp("##start", s) == 0 && check_start(env, s))
		return (1);
	if (ft_strcmp("##end", s) == 0 && check_end(env, s))
		return (1);
	if (is_room(s) && add_room(env, s))
	{
		env->r.nbline += add_file(env, s);
		return (1);
	}
	return (ft_error(env, 1));
}
Ejemplo n.º 27
0
void fs_var_tmp(void) {
	struct stat s;
	if (stat("/var/tmp", &s) == 0) {
		if (!is_link("/var/tmp")) {
			if (arg_debug)
				printf("Mounting tmpfs on /var/tmp\n");
			if (mount("tmpfs", "/var/tmp", "tmpfs", MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME | MS_REC,  "mode=1777,gid=0") < 0)
				errExit("mounting /var/tmp");
			fs_logger("tmpfs /var/tmp");
		}
	}
	else {
		fwarning("/var/tmp not mounted\n");
		dbg_test_dir("/var/tmp");
	}
}
Ejemplo n.º 28
0
static void duplicate(char *fname) {
	char *path = check_dir_or_file(fname);
	if (!path)
		return;

	// expand path, just in case this is a symbolic link
	char *full_path;
	if (asprintf(&full_path, "%s/%s", path, fname) == -1)
		errExit("asprintf");
	
	char *actual_path = realpath(full_path, NULL);
	if (actual_path) {
		// if the file is a symbolic link not under path, make a symbolic link
		if (is_link(full_path) && strncmp(actual_path, path, strlen(path))) {
			char *lnkname;
			if (asprintf(&lnkname, "%s/%s", RUN_BIN_DIR, fname) == -1)
				errExit("asprintf");
			int rv = symlink(actual_path, lnkname);
			if (rv)
				fprintf(stderr, "Warning cannot create symbolic link %s\n", lnkname);
			else if (arg_debug)
				printf("Created symbolic link %s -> %s\n", lnkname, actual_path);
			free(lnkname);
		}
		else {
			// copy the file
			if (arg_debug)
				printf("running: %s -a %s %s/%s", RUN_CP_COMMAND, actual_path, RUN_BIN_DIR, fname);

			pid_t child = fork();
			if (child < 0)
				errExit("fork");
			if (child == 0) {
				char *f;
				if (asprintf(&f, "%s/%s", RUN_BIN_DIR, fname) == -1)
					errExit("asprintf");
				execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", actual_path, f, NULL);
			}
			// wait for the child to finish
			waitpid(child, NULL, 0);
		
		}
		free(actual_path);
	}

	free(full_path);
}
Ejemplo n.º 29
0
void jumpTableEntry::verify() {
  if (is_unused()) {
    // Nothing to check in an unused entry
    return;
  }

  if (is_nmethod_stub()) {
    // Check nmethod
    char* addr = destination();
    if (!Universe::code->contains(addr)) report_verify_error("nmethod not in zone");
    if (method()->entryPoint() != addr)  report_verify_error("destination doesn't point to beginning of nmethod");
    return;
  }

  if (is_link()) {
    // Verify the elements in the list {nmethod} {block_closure}+
    jumpTableEntry* head = jumpTable::jump_entry_for_at(link(), 0);
    if (!head->is_nmethod_stub()) report_verify_error("must be nmethod stub");
    head->verify();
    nmethod* nm = method();
    if (!nm->has_noninlined_blocks()) report_verify_error("nmethod must have noninlined blocks");
    for (int index = 1; index <= nm->number_of_noninlined_blocks(); index++) {
       jumpTableEntry* son = jumpTable::jump_entry_for_at(link(), index);
       if (!son->is_block_closure_stub()) report_verify_error("must be block closure stub");
       son->verify();
    }
    return;
  }

  if (is_block_closure_stub()) {
    char* addr = destination();
    if (!Universe::code->contains(addr)) {
      if (addr != StubRoutines::compile_block_entry())
        report_verify_error("destination points neither into zone nor to compile stub");
    } else {
      nmethod* nm = block_nmethod();
      if (nm->entryPoint() != addr) 
        report_verify_error("destination doesn't point to beginning of nmethod");
    }
    return;
  }

  report_verify_error("invalid state");
}
Ejemplo n.º 30
0
static void duplicate(char *fname) {
	char *cmd;
	char *path = check_dir_or_file(fname);
	if (!path)
		return;

	// expand path, just in case this is a symbolic link
	char *full_path;
	if (asprintf(&full_path, "%s/%s", path, fname) == -1)
		errExit("asprintf");
	
	char *actual_path = realpath(full_path, NULL);
	if (actual_path) {
		// if the file is a symbolic link not under path, make a symbolic link
		if (is_link(full_path) && strncmp(actual_path, path, strlen(path))) {
			char *lnkname;
			if (asprintf(&lnkname, "%s/%s", RUN_BIN_DIR, fname) == -1)
				errExit("asprintf");
			int rv = symlink(actual_path, lnkname);
			if (rv)
				fprintf(stderr, "Warning cannot create symbolic link %s\n", lnkname);
			else if (arg_debug)
				printf("Created symbolic link %s -> %s\n", lnkname, actual_path);
			free(lnkname);
		}
		else {
			// copy the file
			if (asprintf(&cmd, "%s -a %s %s/%s", RUN_CP_COMMAND, actual_path, RUN_BIN_DIR, fname) == -1)
				errExit("asprintf");
			if (arg_debug)
				printf("%s\n", cmd);
			if (system(cmd))
				errExit("system cp -a");
			free(cmd);
		}
		free(actual_path);
	}

	free(full_path);
}