Exemplo n.º 1
0
Arquivo: ln.c Projeto: dezelin/kBuild
int
kmk_builtin_ln(int argc, char *argv[], char **envp)
{
	struct stat sb;
	char *sourcedir;
	int ch, exitval;

	/* initialize globals. */
	fflag = hflag = iflag = sflag = vflag = 0;
	linkch = 0;
	linkf = NULL;

	/* kmk: reset getopt() and set program name. */
	g_progname = argv[0];
	opterr = 1;
	optarg = NULL;
	optopt = 0;
	optind = 0; /* init */

	while ((ch = getopt_long(argc, argv, "fhinsv", long_options, NULL)) != -1)
		switch (ch) {
		case 'f':
			fflag = 1;
			iflag = 0;
			break;
		case 'h':
		case 'n':
			hflag = 1;
			break;
		case 'i':
			iflag = 1;
			fflag = 0;
			break;
		case 's':
			sflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
		case 261:
			usage(stdout);
			return 0;
		case 262:
			return kbuild_version(argv[0]);
		case '?':
		default:
			return usage(stderr);
		}

	argv += optind;
	argc -= optind;

	linkf = sflag ? symlink : link;
	linkch = sflag ? '-' : '=';

	switch(argc) {
	case 0:
		return usage(stderr);
		/* NOTREACHED */
	case 1:				/* ln target */
		return linkit(argv[0], ".", 1);
	case 2:				/* ln target source */
		return linkit(argv[0], argv[1], 0);
	default:
		;
	}
					/* ln target1 target2 directory */
	sourcedir = argv[argc - 1];
	if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
		/*
		 * We were asked not to follow symlinks, but found one at
		 * the target--simulate "not a directory" error
		 */
		errno = ENOTDIR;
		return err(1, "st_mode: %s", sourcedir);
	}
	if (stat(sourcedir, &sb))
		return err(1, "stat: %s", sourcedir);
	if (!S_ISDIR(sb.st_mode))
		return usage(stderr);
	for (exitval = 0; *argv != sourcedir; ++argv)
		exitval |= linkit(*argv, sourcedir, 1);
	return exitval;
}
Exemplo n.º 2
0
/**
 * Appends text to a textfile, creating the textfile if necessary.
 */
int kmk_builtin_append(int argc, char **argv, char **envp)
{
    int i;
    int fFirst;
    int iFile;
    FILE *pFile;
    int fNewline = 0;
    int fNoTrailingNewline = 0;
    int fTruncate = 0;
    int fDefine = 0;
    int fVariables = 0;
    int fCommands = 0;

    g_progname = argv[0];

    /*
     * Parse options.
     */
    i = 1;
    while (i < argc
       &&  argv[i][0] == '-'
       &&  argv[i][1] != '\0' /* '-' is a file */
       &&  strchr("-cdnNtv", argv[i][1]) /* valid option char */
       )
    {
        char *psz = &argv[i][1];
        if (*psz != '-')
        {
            do
            {
                switch (*psz)
                {
                    case 'c':
                        if (fVariables)
                        {
                            errx(1, "Option '-c' clashes with '-v'.");
                            return usage(stderr);
                        }
#ifndef kmk_builtin_append
                        fCommands = 1;
                        break;
#else
                        errx(1, "Option '-c' isn't supported in external mode.");
                        return usage(stderr);
#endif
                    case 'd':
                        if (fVariables)
                        {
                            errx(1, "Option '-d' must come before '-v'!");
                            return usage(stderr);
                        }
                        fDefine = 1;
                        break;
                    case 'n':
                        fNewline = 1;
                        break;
                    case 'N':
                        fNoTrailingNewline = 1;
                        break;
                    case 't':
                        fTruncate = 1;
                        break;
                    case 'v':
                        if (fCommands)
                        {
                            errx(1, "Option '-v' clashes with '-c'.");
                            return usage(stderr);
                        }
#ifndef kmk_builtin_append
                        fVariables = 1;
                        break;
#else
                        errx(1, "Option '-v' isn't supported in external mode.");
                        return usage(stderr);
#endif
                    default:
                        errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]);
                        return usage(stderr);
                }
            } while (*++psz);
        }
        else if (!strcmp(psz, "-help"))
        {
            usage(stdout);
            return 0;
        }
        else if (!strcmp(psz, "-version"))
            return kbuild_version(argv[0]);
        else
            break;
        i++;
    }

    if (i + fDefine >= argc)
    {
        if (i <= argc)
            errx(1, "missing filename!");
        else
            errx(1, "missing define name!");
        return usage(stderr);
    }

    /*
     * Open the output file.
     */
    iFile = i;
    pFile = fopen(argv[i], fTruncate ? "w" : "a");
    if (!pFile)
        return err(1, "failed to open '%s'", argv[i]);

    /*
     * Start define?
     */
    if (fDefine)
    {
        i++;
        fprintf(pFile, "define %s\n", argv[i]);
    }

    /*
     * Append the argument strings to the file
     */
    fFirst = 1;
    for (i++; i < argc; i++)
    {
        const char *psz = argv[i];
        size_t cch = strlen(psz);
        if (!fFirst)
            fputc(fNewline ? '\n' : ' ', pFile);
#ifndef kmk_builtin_append
        if (fCommands)
        {
            char *pszOldBuf;
            unsigned cchOldBuf;
            char *pchEnd;

            install_variable_buffer(&pszOldBuf, &cchOldBuf);

            pchEnd = func_commands(variable_buffer, &argv[i], "commands");
            fwrite(variable_buffer, 1, pchEnd - variable_buffer, pFile);

            restore_variable_buffer(pszOldBuf, cchOldBuf);
        }
        else if (fVariables)
        {
            struct variable *pVar = lookup_variable(psz, cch);
            if (!pVar)
                continue;
            if (   !pVar->recursive
                || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR(pVar))
                fwrite(pVar->value, 1, pVar->value_length, pFile);
            else
            {
                char *pszExpanded = allocated_variable_expand(pVar->value);
                fwrite(pszExpanded, 1, strlen(pszExpanded), pFile);
                free(pszExpanded);
            }
        }
        else
#endif
            fwrite(psz, 1, cch, pFile);
        fFirst = 0;
    }

    /*
     * End the define?
     */
    if (fDefine)
    {
        if (fFirst)
            fwrite("\nendef", 1, sizeof("\nendef") - 1, pFile);
        else
            fwrite("endef", 1, sizeof("endef") - 1, pFile);
    }

    /*
     * Add the final newline (unless supressed) and close the file.
     */
    if (    (   !fNoTrailingNewline
             && fputc('\n', pFile) == EOF)
        ||  ferror(pFile))
    {
        fclose(pFile);
        return errx(1, "error writing to '%s'!", argv[iFile]);
    }
    if (fclose(pFile))
        return err(1, "failed to fclose '%s'!", argv[iFile]);
    return 0;
}
Exemplo n.º 3
0
int
kmk_builtin_chmod(int argc, char *argv[], char **envp)
{
	FTS *ftsp;
	FTSENT *p;
	mode_t *set;
	int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval;
	int vflag;
	char *mode;
	mode_t newmode;
	int (*change_mode)(const char *, mode_t);

	/* kmk: reset getopt and set progname */
	g_progname = argv[0];
	opterr = 1;
	optarg = NULL;
	optopt = 0;
	optind = 0; /* init */

	set = NULL;
	Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
	while ((ch = getopt_long(argc, argv, "HLPRXfghorstuvwx", long_options, NULL)) != -1)
		switch (ch) {
		case 'H':
			Hflag = 1;
			Lflag = 0;
			break;
		case 'L':
			Lflag = 1;
			Hflag = 0;
			break;
		case 'P':
			Hflag = Lflag = 0;
			break;
		case 'R':
			Rflag = 1;
			break;
		case 'f':
			fflag = 1;
			break;
		case 'h':
			/*
			 * In System V (and probably POSIX.2) the -h option
			 * causes chmod to change the mode of the symbolic
			 * link.  4.4BSD's symbolic links didn't have modes,
			 * so it was an undocumented noop.  In FreeBSD 3.0,
			 * lchmod(2) is introduced and this option does real
			 * work.
			 */
			hflag = 1;
			break;
		/*
		 * XXX
		 * "-[rwx]" are valid mode commands.  If they are the entire
		 * argument, getopt has moved past them, so decrement optind.
		 * Regardless, we're done argument processing.
		 */
		case 'g': case 'o': case 'r': case 's':
		case 't': case 'u': case 'w': case 'X': case 'x':
			if (argv[optind - 1][0] == '-' &&
			    argv[optind - 1][1] == ch &&
			    argv[optind - 1][2] == '\0')
				--optind;
			goto done;
		case 'v':
			vflag++;
			break;
		case 261:
			usage(stdout);
			return 0;
		case 262:
			return kbuild_version(argv[0]);
		case '?':
		default:
			return usage(stderr);
		}
done:	argv += optind;
	argc -= optind;

	if (argc < 2)
		return usage(stderr);

	if (Rflag) {
		fts_options = FTS_PHYSICAL;
		if (hflag)
			return errx(1,
		"the -R and -h options may not be specified together.");
		if (Hflag)
			fts_options |= FTS_COMFOLLOW;
		if (Lflag) {
			fts_options &= ~FTS_PHYSICAL;
			fts_options |= FTS_LOGICAL;
		}
	} else
		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;

	if (hflag)
		change_mode = lchmod;
	else
		change_mode = chmod;

	mode = *argv;
	if ((set = bsd_setmode(mode)) == NULL)
		return errx(1, "invalid file mode: %s", mode);

	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
		return err(1, "fts_open");
	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
		switch (p->fts_info) {
		case FTS_D:			/* Change it at FTS_DP. */
			if (!Rflag)
				fts_set(ftsp, p, FTS_SKIP);
			continue;
		case FTS_DNR:			/* Warn, chmod, continue. */
			warnx("fts: %s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			break;
		case FTS_ERR:			/* Warn, continue. */
		case FTS_NS:
			warnx("fts: %s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			continue;
		case FTS_SL:			/* Ignore. */
		case FTS_SLNONE:
			/*
			 * The only symlinks that end up here are ones that
			 * don't point to anything and ones that we found
			 * doing a physical walk.
			 */
			if (!hflag)
				continue;
			/* else */
			/* FALLTHROUGH */
		default:
			break;
		}
		newmode = bsd_getmode(set, p->fts_statp->st_mode);
		if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
			continue;
		if ((*change_mode)(p->fts_accpath, newmode) && !fflag) {
			warn("%schmod: %s", hflag ? "l" : "", p->fts_path);
			rval = 1;
		} else {
			if (vflag) {
				(void)printf("%s", p->fts_path);

				if (vflag > 1) {
					char m1[12], m2[12];

					bsd_strmode(p->fts_statp->st_mode, m1);
					bsd_strmode((p->fts_statp->st_mode &
					    S_IFMT) | newmode, m2);

					(void)printf(": 0%o [%s] -> 0%o [%s]",
					    (unsigned int)p->fts_statp->st_mode, m1,
					    (unsigned int)((p->fts_statp->st_mode & S_IFMT) | newmode), m2);
				}
				(void)printf("\n");
			}

		}
	}
	if (errno)
		rval = err(1, "fts_read");
	free(set);
	fts_close(ftsp);
	return rval;
}
Exemplo n.º 4
0
int kmk_builtin_test(int argc, char **argv, char **envp, char ***ppapszArgvSpawn)
{
	int res;
	char **argv_spawn;
	int i;

	g_progname = argv[0];

	/* look for the '--', '--help' and '--version'. */
	argv_spawn = NULL;
	for (i = 1; i < argc; i++) {
		if (   argv[i][0] == '-'
		    && argv[i][1] == '-') {
    			if (argv[i][2] == '\0') {
				argc = i;
				argv[i] = NULL;

                                /* skip blank arguments (happens inside kmk) */
                                while (argv[++i]) {
                                        const char *psz = argv[i];
                                        while (isspace(*psz))
                                                psz++;
                                        if (*psz)
                                                break;
                                }
				argv_spawn = &argv[i];
				break;
			}
			if (!strcmp(argv[i], "--help"))
				return usage(argv[0]);
			if (!strcmp(argv[i], "--version"))
				return kbuild_version(argv[0]);
		}
	}

	/* are we '['? then check for ']'. */
	if (strcmp(g_progname, "[") == 0) { /** @todo should skip the path in g_progname */
		if (strcmp(argv[--argc], "]"))
			return errx(1, "missing ]");
		argv[argc] = NULL;
	}

	/* evaluate the expression */
	if (argc < 2)
		res = 1;
	else {
		t_wp = &argv[1];
		res = oexpr(t_lex(*t_wp));
		if (res != -42 && *t_wp != NULL && *++t_wp != NULL)
			res = syntax(*t_wp, "unexpected operator");
		if (res == -42)
			return 1; /* don't mix syntax errors with the argv_spawn ignore */
		res = !res;
	}

	/* anything to execute on success? */
	if (argv_spawn) {
		if (res != 0 || !argv_spawn[0])
			res = 0; /* ignored */
		else {
#ifdef kmk_builtin_test
			/* try exec the specified process */
# if defined(_MSC_VER)
			res = _spawnvp(_P_WAIT, argv_spawn[0], argv_spawn);
			if (res == -1)
			    res = err(1, "_spawnvp(_P_WAIT,%s,..)", argv_spawn[0]);
# else
			execvp(argv_spawn[0], argv_spawn);
			res = err(1, "execvp(%s,..)", argv_spawn[0]);
# endif
#else /* in kmk */
			/* let job.c spawn the process, make a job.c style argv_spawn copy. */
			char *buf, *cur, **argv_new;
			size_t sz = 0;
			int argc_new = 0;
			while (argv_spawn[argc_new]) {
    				size_t len = strlen(argv_spawn[argc_new]) + 1;
				sz += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
				argc_new++;
			}

			argv_new = xmalloc((argc_new + 1) * sizeof(char *));
			buf = cur = xmalloc(sz);
			for (i = 0; i < argc_new; i++) {
				size_t len = strlen(argv_spawn[i]) + 1;
				argv_new[i] = memcpy(cur, argv_spawn[i], len);
				cur += (len + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
			}
			argv_new[i] = NULL;

			*ppapszArgvSpawn = argv_new;
			res = 0;
#endif /* in kmk */
		}
	}

	return res;
}
Exemplo n.º 5
0
Arquivo: rm.c Projeto: dezelin/kBuild
/*
 * rm --
 *	This rm is different from historic rm's, but is expected to match
 *	POSIX 1003.2 behavior.  The most visible difference is that -f
 *	has two specific effects now, ignore non-existent files and force
 * 	file removal.
 */
int
kmk_builtin_rm(int argc, char *argv[], char **envp)
{
	int ch, rflag;

	/* reinitialize globals */
	argv0 = argv[0];
	dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0;
	uid = 0;
	kBuildProtectionInit(&g_ProtData);

	/* kmk: reset getopt and set program name. */
	g_progname = argv[0];
	opterr = 1;
	optarg = NULL;
	optopt = 0;
	optind = 0; /* init */

	Pflag = rflag = 0;
	while ((ch = getopt_long(argc, argv, "dfiPRvW", long_options, NULL)) != -1)
		switch(ch) {
		case 'd':
			dflag = 1;
			break;
		case 'f':
			fflag = 1;
			iflag = 0;
			break;
		case 'i':
			fflag = 0;
			iflag = 1;
			break;
		case 'P':
			Pflag = 1;
			break;
		case 'R':
#if 0
		case 'r':			/* Compatibility. */
#endif
			rflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
#ifdef FTS_WHITEOUT
		case 'W':
			Wflag = 1;
			break;
#endif
		case 261:
			kBuildProtectionTerm(&g_ProtData);
			usage(stdout);
			return 0;
		case 262:
			kBuildProtectionTerm(&g_ProtData);
			return kbuild_version(argv[0]);
		case 263:
			kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
			break;
		case 264:
			kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
			break;
		case 265:
			kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
			break;
		case 266:
			kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
			break;
		case 267:
			if (kBuildProtectionSetDepth(&g_ProtData, optarg)) {
			    kBuildProtectionTerm(&g_ProtData);
			    return 1;
			}
			break;
		case '?':
		default:
			kBuildProtectionTerm(&g_ProtData);
			return usage(stderr);
		}
	argc -= optind;
	argv += optind;

	if (argc < 1) {
		kBuildProtectionTerm(&g_ProtData);
		if (fflag)
			return (0);
		return usage(stderr);
	}

	if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_RM_")) {
		checkdot(argv);
		uid = geteuid();

		if (*argv) {
			stdin_ok = isatty(STDIN_FILENO);
			if (rflag)
				eval |= rm_tree(argv);
			else
				eval |= rm_file(argv);
		}
	} else {
		eval = 1;
	}

	kBuildProtectionTerm(&g_ProtData);
	return eval;
}