Exemple #1
0
int
main(int argc, char *argv[])
{
	int		 ch;
	char		*aux, *base, *conf_file;
	struct manpaths	 dirs;
	char		 buf[MAXPATHLEN];
	extern char	*optarg;
	extern int	 optind;

	progname = strrchr(argv[0], '/');
	if (progname == NULL)
		progname = argv[0];
	else
		++progname;

	aux = base = conf_file = NULL;
	xstrlcpy(buf, "/var/www/cache/man.cgi", MAXPATHLEN);

	while (-1 != (ch = getopt(argc, argv, "C:fm:M:o:v")))
		switch (ch) {
		case ('C'):
			conf_file = optarg;
			break;
		case ('f'):
			force = 1;
			break;
		case ('m'):
			aux = optarg;
			break;
		case ('M'):
			base = optarg;
			break;
		case ('o'):
			xstrlcpy(buf, optarg, MAXPATHLEN);
			break;
		case ('v'):
			verbose++;
			break;
		default:
			usage();
			return(EXIT_FAILURE);
		}

	argc -= optind;
	argv += optind;

	if (argc > 0) {
		usage();
		return(EXIT_FAILURE);
	}

	memset(&dirs, 0, sizeof(struct manpaths));
	manpath_parse(&dirs, conf_file, base, aux);
	ch = manup(&dirs, buf);
	manpath_free(&dirs);
	return(ch ? EXIT_SUCCESS : EXIT_FAILURE);
}
Exemple #2
0
int
main(int argc, char *argv[])
{
	struct mparse	*mp; /* parse sequence */
	struct manpaths	 dirs;
	struct mdb	 mdb;
	struct recs	 recs;
	enum op		 op; /* current operation */
	const char	*dir;
	int		 ch, i, flags;
	char		 dirbuf[MAXPATHLEN];
	DB		*hash; /* temporary keyword hashtable */
	BTREEINFO	 info; /* btree configuration */
	size_t		 sz1, sz2;
	struct buf	 buf, /* keyword buffer */
			 dbuf; /* description buffer */
	struct of	*of; /* list of files for processing */
	extern int	 optind;
	extern char	*optarg;

	progname = strrchr(argv[0], '/');
	if (progname == NULL)
		progname = argv[0];
	else
		++progname;

	memset(&dirs, 0, sizeof(struct manpaths));
	memset(&mdb, 0, sizeof(struct mdb));
	memset(&recs, 0, sizeof(struct recs));

	of = NULL;
	mp = NULL;
	hash = NULL;
	op = OP_DEFAULT;
	dir = NULL;

	while (-1 != (ch = getopt(argc, argv, "aC:d:tu:vW")))
		switch (ch) {
		case ('a'):
			use_all = 1;
			break;
		case ('C'):
			if (op) {
				fprintf(stderr,
				    "-C: conflicting options\n");
				goto usage;
			}
			dir = optarg;
			op = OP_CONFFILE;
			break;
		case ('d'):
			if (op) {
				fprintf(stderr,
				    "-d: conflicting options\n");
				goto usage;
			}
			dir = optarg;
			op = OP_UPDATE;
			break;
		case ('t'):
			dup2(STDOUT_FILENO, STDERR_FILENO);
			if (op) {
				fprintf(stderr,
				    "-t: conflicting options\n");
				goto usage;
			}
			op = OP_TEST;
			use_all = 1;
			warnings = 1;
			break;
		case ('u'):
			if (op) {
				fprintf(stderr,
				    "-u: conflicting options\n");
				goto usage;
			}
			dir = optarg;
			op = OP_DELETE;
			break;
		case ('v'):
			verb++;
			break;
		case ('W'):
			warnings = 1;
			break;
		default:
			goto usage;
		}

	argc -= optind;
	argv += optind;

	if (OP_CONFFILE == op && argc > 0) {
		fprintf(stderr, "-C: too many arguments\n");
		goto usage;
	}

	memset(&info, 0, sizeof(BTREEINFO));
	info.lorder = 4321;
	info.flags = R_DUP;

	mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);

	memset(&buf, 0, sizeof(struct buf));
	memset(&dbuf, 0, sizeof(struct buf));

	buf.size = dbuf.size = MANDOC_BUFSZ;

	buf.cp = mandoc_malloc(buf.size);
	dbuf.cp = mandoc_malloc(dbuf.size);

	if (OP_TEST == op) {
		ofile_argbuild(argc, argv, &of, ".");
		if (NULL == of)
			goto out;
		index_merge(of, mp, &dbuf, &buf, 
				hash, &mdb, &recs, ".");
		goto out;
	}

	if (OP_UPDATE == op || OP_DELETE == op) {
		strlcat(mdb.dbn, dir, MAXPATHLEN);
		strlcat(mdb.dbn, "/", MAXPATHLEN);
		sz1 = strlcat(mdb.dbn, MANDOC_DB, MAXPATHLEN);

		strlcat(mdb.idxn, dir, MAXPATHLEN);
		strlcat(mdb.idxn, "/", MAXPATHLEN);
		sz2 = strlcat(mdb.idxn, MANDOC_IDX, MAXPATHLEN);

		if (sz1 >= MAXPATHLEN || sz2 >= MAXPATHLEN) {
			fprintf(stderr, "%s: path too long\n", dir);
			exit((int)MANDOCLEVEL_BADARG);
		}

		flags = O_CREAT | O_RDWR;
		mdb.db = dbopen(mdb.dbn, flags, 0644, DB_BTREE, &info);
		mdb.idx = dbopen(mdb.idxn, flags, 0644, DB_RECNO, NULL);

		if (NULL == mdb.db) {
			perror(mdb.dbn);
			exit((int)MANDOCLEVEL_SYSERR);
		} else if (NULL == mdb.idx) {
			perror(mdb.idxn);
			exit((int)MANDOCLEVEL_SYSERR);
		}

		ofile_argbuild(argc, argv, &of, dir);

		if (NULL == of)
			goto out;

		index_prune(of, &mdb, &recs, dir);

		/*
		 * Go to the root of the respective manual tree.
		 * This must work or no manuals may be found (they're
		 * indexed relative to the root).
		 */

		if (OP_UPDATE == op) {
			if (-1 == chdir(dir)) {
				perror(dir);
				exit((int)MANDOCLEVEL_SYSERR);
			}
			index_merge(of, mp, &dbuf, &buf, hash,
					&mdb, &recs, dir);
		}

		goto out;
	}

	/*
	 * Configure the directories we're going to scan.
	 * If we have command-line arguments, use them.
	 * If not, we use man(1)'s method (see mandocdb.8).
	 */

	if (argc > 0) {
		dirs.paths = mandoc_calloc(argc, sizeof(char *));
		dirs.sz = argc;
		for (i = 0; i < argc; i++) 
			dirs.paths[i] = mandoc_strdup(argv[i]);
	} else
		manpath_parse(&dirs, dir, NULL, NULL);

	for (i = 0; i < dirs.sz; i++) {
		/*
		 * Go to the root of the respective manual tree.
		 * This must work or no manuals may be found:
		 * They are indexed relative to the root.
		 */

		if (-1 == chdir(dirs.paths[i])) {
			perror(dirs.paths[i]);
			exit((int)MANDOCLEVEL_SYSERR);
		}

		strlcpy(mdb.dbn, MANDOC_DB, MAXPATHLEN);
		strlcpy(mdb.idxn, MANDOC_IDX, MAXPATHLEN);

		flags = O_CREAT | O_TRUNC | O_RDWR;
		mdb.db = dbopen(mdb.dbn, flags, 0644, DB_BTREE, &info);
		mdb.idx = dbopen(mdb.idxn, flags, 0644, DB_RECNO, NULL);

		if (NULL == mdb.db) {
			perror(mdb.dbn);
			exit((int)MANDOCLEVEL_SYSERR);
		} else if (NULL == mdb.idx) {
			perror(mdb.idxn);
			exit((int)MANDOCLEVEL_SYSERR);
		}

		/*
		 * Search for manuals and fill the new database.
		 */

		strlcpy(dirbuf, dirs.paths[i], MAXPATHLEN);
	       	ofile_dirbuild(".", "", "", 0, &of, dirbuf);

		if (NULL != of) {
			index_merge(of, mp, &dbuf, &buf, hash,
			     &mdb, &recs, dirs.paths[i]);
			ofile_free(of);
			of = NULL;
		}

		(*mdb.db->close)(mdb.db);
		(*mdb.idx->close)(mdb.idx);
		mdb.db = NULL;
		mdb.idx = NULL;
	}

out:
	if (mdb.db)
		(*mdb.db->close)(mdb.db);
	if (mdb.idx)
		(*mdb.idx->close)(mdb.idx);
	if (hash)
		(*hash->close)(hash);
	if (mp)
		mparse_free(mp);

	manpath_free(&dirs);
	ofile_free(of);
	free(buf.cp);
	free(dbuf.cp);
	free(recs.stack);

	return(MANDOCLEVEL_OK);

usage:
	fprintf(stderr,
		"usage: %s [-av] [-C file] | dir ... | -t file ...\n"
		"                        -d dir [file ...] | "
		"-u dir [file ...]\n",
		progname);

	return((int)MANDOCLEVEL_BADARG);
}
Exemple #3
0
int
main(int argc, char *argv[])
{
	int		 ch, term;
	size_t		 i, sz, len;
	struct mansearch search;
	struct manpage	*res;
	char		*conf_file, *defpaths, *auxpaths, *cp;
	char		 buf[PATH_MAX];
	const char	*cmd;
	struct manpaths	 paths;
	char		*progname;
	extern char	*optarg;
	extern int	 optind;

	term = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);

	progname = strrchr(argv[0], '/');
	if (progname == NULL)
		progname = argv[0];
	else
		++progname;

	auxpaths = defpaths = conf_file = NULL;
	memset(&paths, 0, sizeof(struct manpaths));
	memset(&search, 0, sizeof(struct mansearch));

	while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
		switch (ch) {
		case ('C'):
			conf_file = optarg;
			break;
		case ('M'):
			defpaths = optarg;
			break;
		case ('m'):
			auxpaths = optarg;
			break;
		case ('S'):
			search.arch = optarg;
			break;
		case ('s'):
			search.sec = optarg;
			break;
		default:
			goto usage;
		}

	argc -= optind;
	argv += optind;

	if (0 == argc)
		goto usage;

	search.deftype = TYPE_Nm | TYPE_Nd;

	manpath_parse(&paths, conf_file, defpaths, auxpaths);
	ch = mansearch(&search, &paths, argc, argv, "Nd", &res, &sz);
	manpath_free(&paths);

	if (0 == ch)
		goto usage;

	if (0 == sz) {
		free(res);
		return(EXIT_FAILURE);
	} else if (1 == sz && term) {
		i = 1;
		goto show;
	} else if (NULL == res)
		return(EXIT_FAILURE);

	for (i = 0; i < sz; i++) {
		printf("%6zu  %s: %s\n", 
			i + 1, res[i].names, res[i].output);
		free(res[i].names);
		free(res[i].output);
	}

	if (0 == term) {
		for (i = 0; i < sz; i++)
			free(res[i].file);
		free(res);
		return(EXIT_SUCCESS);
	}

	i = 1;
	printf("Enter a choice [1]: ");
	fflush(stdout);

	if (NULL != (cp = fgetln(stdin, &len)))
		if ('\n' == cp[--len] && len > 0) {
			cp[len] = '\0';
			if ((i = atoi(cp)) < 1 || i > sz)
				i = 0;
		}

	if (0 == i) {
		for (i = 0; i < sz; i++)
			free(res[i].file);
		free(res);
		return(EXIT_SUCCESS);
	}
show:
	cmd = res[i - 1].form ? "mandoc" : "cat";
	strlcpy(buf, res[i - 1].file, PATH_MAX);
	for (i = 0; i < sz; i++)
		free(res[i].file);
	free(res);

	show(cmd, buf);
	/* NOTREACHED */
usage:
	fprintf(stderr, "usage: %s [-C conf] "
			 	  "[-M paths] "
				  "[-m paths] "
				  "[-S arch] "
				  "[-s section] "
			          "expr ...\n", 
				  progname);
	return(EXIT_FAILURE);
}
Exemple #4
0
int
main(int argc, char *argv[])
{
    int		 ch, rc, whatis;
    struct manpaths	 paths;
    size_t		 terms;
    struct opts	 opts;
    struct expr	*e;
    char		*defpaths, *auxpaths;
    char		*conf_file;
    extern int	 optind;
    extern char	*optarg;

    progname = strrchr(argv[0], '/');
    if (progname == NULL)
        progname = argv[0];
    else
        ++progname;

    whatis = 0 == strncmp(progname, "whatis", 6);

    memset(&paths, 0, sizeof(struct manpaths));
    memset(&opts, 0, sizeof(struct opts));

    auxpaths = defpaths = NULL;
    conf_file = NULL;
    e = NULL;

    while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
        switch (ch) {
        case ('C'):
            conf_file = optarg;
            break;
        case ('M'):
            defpaths = optarg;
            break;
        case ('m'):
            auxpaths = optarg;
            break;
        case ('S'):
            opts.arch = optarg;
            break;
        case ('s'):
            opts.cat = optarg;
            break;
        default:
            usage();
            return(EXIT_FAILURE);
        }

    argc -= optind;
    argv += optind;

    if (0 == argc)
        return(EXIT_SUCCESS);

    rc = 0;

    manpath_parse(&paths, conf_file, defpaths, auxpaths);

    e = whatis ? termcomp(argc, argv, &terms) :
        exprcomp(argc, argv, &terms);

    if (NULL == e) {
        fprintf(stderr, "%s: Bad expression\n", progname);
        goto out;
    }

    rc = apropos_search
         (paths.sz, paths.paths,
          &opts, e, terms, NULL, list);

    if (0 == rc)
        fprintf(stderr, "%s: Error reading "
                "manual database\n", progname);

out:
    manpath_free(&paths);
    exprfree(e);

    return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
}
Exemple #5
0
static void
pg_search(const struct req *req, char *path)
{
	size_t		  tt, ressz;
	struct manpaths	  ps;
	int		  i, sz, rc;
	const char	 *ep, *start;
	struct res	*res;
	char		**cp;
	struct opts	  opt;
	struct expr	 *expr;

	if (req->q.manroot < 0 || 0 == req->psz) {
		resp_search(NULL, 0, (void *)req);
		return;
	}

	memset(&opt, 0, sizeof(struct opts));

	ep 	 = req->q.expr;
	opt.arch = req->q.arch;
	opt.cat  = req->q.sec;
	rc 	 = -1;
	sz 	 = 0;
	cp	 = NULL;
	ressz	 = 0;
	res	 = NULL;

	/*
	 * Begin by chdir()ing into the root of the manpath.
	 * This way we can pick up the database files, which are
	 * relative to the manpath root.
	 */

	assert(req->q.manroot < (int)req->psz);
	if (-1 == (chdir(req->p[req->q.manroot].path))) {
		perror(req->p[req->q.manroot].path);
		resp_search(NULL, 0, (void *)req);
		return;
	}

	memset(&ps, 0, sizeof(struct manpaths));
	manpath_manconf(&ps, "etc/catman.conf");

	/*
	 * Poor man's tokenisation: just break apart by spaces.
	 * Yes, this is half-ass.  But it works for now.
	 */

	while (ep && isspace((unsigned char)*ep))
		ep++;

	while (ep && '\0' != *ep) {
		cp = mandoc_realloc(cp, (sz + 1) * sizeof(char *));
		start = ep;
		while ('\0' != *ep && ! isspace((unsigned char)*ep))
			ep++;
		cp[sz] = mandoc_malloc((ep - start) + 1);
		memcpy(cp[sz], start, ep - start);
		cp[sz++][ep - start] = '\0';
		while (isspace((unsigned char)*ep))
			ep++;
	}

	/*
	 * Pump down into apropos backend.
	 * The resp_search() function is called with the results.
	 */

	expr = req->q.legacy ? 
		termcomp(sz, cp, &tt) : exprcomp(sz, cp, &tt);

	if (NULL != expr)
		rc = apropos_search
			(ps.sz, ps.paths, &opt, expr, tt, 
			 (void *)req, &ressz, &res, resp_search);

	/* ...unless errors occured. */

	if (0 == rc)
		resp_baddb();
	else if (-1 == rc)
		resp_search(NULL, 0, NULL);

	for (i = 0; i < sz; i++)
		free(cp[i]);

	free(cp);
	resfree(res, ressz);
	exprfree(expr);
	manpath_free(&ps);
}
Exemple #6
0
static void
pg_show(const struct req *req, char *path)
{
	struct manpaths	 ps;
	size_t		 sz;
	char		*sub;
	char		 file[PATH_MAX];
	const char	*cp;
	int		 rc, catm;
	unsigned int	 vol, rec, mr;
	DB		*idx;
	DBT		 key, val;

	idx = NULL;

	/* Parse out mroot, volume, and record from the path. */

	if (NULL == path || NULL == (sub = strchr(path, '/'))) {
		resp_error400();
		return;
	} 
	*sub++ = '\0';
	if ( ! atou(path, &mr)) {
		resp_error400();
		return;
	}
	path = sub;
	if (NULL == (sub = strchr(path, '/'))) {
		resp_error400();
		return;
	}
	*sub++ = '\0';
	if ( ! atou(path, &vol) || ! atou(sub, &rec)) {
		resp_error400();
		return;
	} else if (mr >= (unsigned int)req->psz) {
		resp_error400();
		return;
	}

	/*
	 * Begin by chdir()ing into the manroot.
	 * This way we can pick up the database files, which are
	 * relative to the manpath root.
	 */

	if (-1 == chdir(req->p[(int)mr].path)) {
		perror(req->p[(int)mr].path);
		resp_baddb();
		return;
	}

	memset(&ps, 0, sizeof(struct manpaths));
	manpath_manconf(&ps, "etc/catman.conf");

	if (vol >= (unsigned int)ps.sz) {
		resp_error400();
		goto out;
	}

	sz = strlcpy(file, ps.paths[vol], PATH_MAX);
	assert(sz < PATH_MAX);
	strlcat(file, "/", PATH_MAX);
	strlcat(file, MANDOC_IDX, PATH_MAX);

	/* Open the index recno(3) database. */

	idx = dbopen(file, O_RDONLY, 0, DB_RECNO, NULL);
	if (NULL == idx) {
		perror(file);
		resp_baddb();
		goto out;
	}

	key.data = &rec;
	key.size = 4;

	if (0 != (rc = (*idx->get)(idx, &key, &val, 0))) {
		rc < 0 ? resp_baddb() : resp_error400();
		goto out;
	} else if (0 == val.size) {
		resp_baddb();
		goto out;
	}

	cp = (char *)val.data;
	catm = 'c' == *cp++;

	if (NULL == memchr(cp, '\0', val.size - 1)) 
		resp_baddb();
	else {
 		file[(int)sz] = '\0';
 		strlcat(file, "/", PATH_MAX);
 		strlcat(file, cp, PATH_MAX);
		if (catm) 
			catman(req, file);
		else
			format(req, file);
	}
out:
	if (idx)
		(*idx->close)(idx);
	manpath_free(&ps);
}
Exemple #7
0
int
apropos(int argc, char *argv[])
{
	int		 ch, rc, whatis;
	struct res	*res;
	struct manpaths	 paths;
	size_t		 terms, ressz;
	struct opts	 opts;
	struct expr	*e;
	char		*defpaths, *auxpaths;
	char		*conf_file;
	extern char	*optarg;
	extern int	 optind;

	progname = strrchr(argv[0], '/');
	if (progname == NULL)
		progname = argv[0];
	else
		++progname;

	whatis = (0 == strncmp(progname, "whatis", 6));

	memset(&paths, 0, sizeof(struct manpaths));
	memset(&opts, 0, sizeof(struct opts));

	ressz = 0;
	res = NULL;
	auxpaths = defpaths = NULL;
	conf_file = NULL;
	e = NULL;

	while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
		switch (ch) {
		case ('C'):
			conf_file = optarg;
			break;
		case ('M'):
			defpaths = optarg;
			break;
		case ('m'):
			auxpaths = optarg;
			break;
		case ('S'):
			opts.arch = optarg;
			break;
		case ('s'):
			opts.cat = optarg;
			break;
		default:
			goto usage;
		}

	argc -= optind;
	argv += optind;

	if (0 == argc)
		goto usage;

	rc = 0;

	manpath_parse(&paths, conf_file, defpaths, auxpaths);

	e = whatis ? termcomp(argc, argv, &terms) :
		     exprcomp(argc, argv, &terms);
		
	if (NULL == e) {
		fprintf(stderr, "%s: Bad expression\n", progname);
		goto out;
	}

	rc = apropos_search
		(paths.sz, paths.paths, &opts, 
		 e, terms, NULL, &ressz, &res, list);

	if (0 == rc) {
		fprintf(stderr, "%s: Bad database\n", progname);
		goto out;
	}

out:
	manpath_free(&paths);
	resfree(res, ressz);
	exprfree(e);
	return(rc ? EXIT_SUCCESS : EXIT_FAILURE);

usage:
	fprintf(stderr, "usage: %s [-C file] [-M path] [-m path] "
			"[-S arch] [-s section]%s ...\n", progname,
			whatis ? " name" : "\n               expression");
	return(EXIT_FAILURE);
}