FreeBSD/usr.sbin/jail/config.c
/*
 * Parse the jail configuration file.
 */
Parse the jail configuration file.
Parse the jail configuration file .
void
load_config(void)
{
	struct cfjails wild;
	struct cfparams opp;
	struct cfjail *j, *tj, *wj;
	struct cfparam *p, *vp, *tp;
	struct cfstring *s, *vs, *ns;
	struct cfvar *v, *vv;
	char *ep;
	int did_self, jseq, pgen;
	if (!strcmp(cfname, "-")) {
		cfname = "STDIN";
		yyin = stdin;
	} else {
		yyin = fopen(cfname, "r");
		if (!yyin)
			err(1, "%s", cfname);
	}
	if (yyparse() || yynerrs)
		exit(1);
	jseq = 0;
	TAILQ_INIT(&wild);
	TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
		j->seq = ++jseq;
		if (wild_jail_name(j->name))
			requeue(j, &wild);
	}
	TAILQ_FOREACH(j, &cfjails, tq) {
		TAILQ_INIT(&opp);
		TAILQ_CONCAT(&opp, &j->params, tq);
		add_param(j, NULL,
		    strtol(j->name, &ep, 10) && !*ep ? KP_JID : KP_NAME,
		    j->name);
		did_self = 0;
		TAILQ_FOREACH(wj, &wild, tq) {
			if (j->seq < wj->seq && !did_self) {
				TAILQ_FOREACH(p, &opp, tq)
					add_param(j, p, 0, NULL);
				did_self = 1;
			}
			if (wild_jail_match(j->name, wj->name))
				TAILQ_FOREACH(p, &wj->params, tq)
					add_param(j, p, 0, NULL);
		}
		if (!did_self)
			TAILQ_FOREACH(p, &opp, tq)
				add_param(j, p, 0, NULL);
		pgen = 0;
		TAILQ_FOREACH(p, &j->params, tq) {
		    p->gen = ++pgen;
		find_vars:
		    TAILQ_FOREACH(s, &p->val, tq) {
			while ((v = STAILQ_FIRST(&s->vars))) {
				TAILQ_FOREACH(vp, &j->params, tq)
					if (!strcmp(vp->name, v->name))
						break;
				if (!vp) {
					jail_warnx(j,
					    "%s: variable \"%s\" not found",
					    p->name, v->name);
				bad_var:
					j->flags |= JF_FAILED;
					TAILQ_FOREACH(vp, &j->params, tq)
						if (vp->gen == pgen)
							vp->flags |= PF_BAD;
					goto free_var;
				}
				if (vp->flags & PF_BAD)
					goto bad_var;
				if (vp->gen == pgen) {
					jail_warnx(j, "%s: variable loop",
					    v->name);
					goto bad_var;
				}
				TAILQ_FOREACH(vs, &vp->val, tq)
					if (!STAILQ_EMPTY(&vs->vars)) {
						vp->gen = pgen;
						TAILQ_REMOVE(&j->params, vp,
						    tq);
						TAILQ_INSERT_BEFORE(p, vp, tq);
						p = vp;
						goto find_vars;
					}
				vs = TAILQ_FIRST(&vp->val);
				if (TAILQ_NEXT(vs, tq) != NULL &&
				    (s->s[0] != '\0' ||
				     STAILQ_NEXT(v, tq))) {
					jail_warnx(j, "%s: array cannot be "
					    "substituted inline",
					    p->name);
					goto bad_var;
				}
				s->s = erealloc(s->s, s->len + vs->len + 1);
				memmove(s->s + v->pos + vs->len,
				    s->s + v->pos,
				    s->len - v->pos + 1);
				memcpy(s->s + v->pos, vs->s, vs->len);
				vv = v;
				while ((vv = STAILQ_NEXT(vv, tq)))
					vv->pos += vs->len;
				s->len += vs->len;
				while ((vs = TAILQ_NEXT(vs, tq))) {
					ns = emalloc(sizeof(struct cfstring));
					ns->s = estrdup(vs->s);
					ns->len = vs->len;
					STAILQ_INIT(&ns->vars);
					TAILQ_INSERT_AFTER(&p->val, s, ns, tq);
					s = ns;
				}
			free_var:
				free(v->name);
				STAILQ_REMOVE_HEAD(&s->vars, tq);
				free(v);
			}
		    }
		}
		while ((p = TAILQ_FIRST(&opp)))
			free_param(&opp, p);
		TAILQ_FOREACH_SAFE(p, &j->params, tq, tp)
			if (p->flags & PF_VAR)
				free_param(&j->params, p);
	}
	while ((wj = TAILQ_FIRST(&wild))) {
		free(wj->name);
		while ((p = TAILQ_FIRST(&wj->params)))
			free_param(&wj->params, p);
		TAILQ_REMOVE(&wild, wj, tq);
	}
}
void load_config ( void ) { struct cfjails wild ; struct cfparams opp ; struct cfjail * j , * tj , * wj ; struct cfparam * p , * vp , * tp ; struct cfstring * s , * vs , * ns ; struct cfvar * v , * vv ; char * ep ; int did_self , jseq , pgen ; if ( ! strcmp ( cfname , " " ) ) { cfname = " " ; yyin = stdin ; } else { yyin = fopen ( cfname , " " ) ; if ( ! yyin ) err ( 1 , " " , cfname ) ; } if ( yyparse ( ) || yynerrs ) exit ( 1 ) ; jseq = 0 ; TAILQ_INIT ( & wild ) ; TAILQ_FOREACH_SAFE ( j , & cfjails , tq , tj ) { j -> seq = ++ jseq ; if ( wild_jail_name ( j -> name ) ) requeue ( j , & wild ) ; } TAILQ_FOREACH ( j , & cfjails , tq ) { TAILQ_INIT ( & opp ) ; TAILQ_CONCAT ( & opp , & j -> params , tq ) ; add_param ( j , NULL , strtol ( j -> name , & ep , 10 ) && ! * ep ? KP_JID : KP_NAME , j -> name ) ; did_self = 0 ; TAILQ_FOREACH ( wj , & wild , tq ) { if ( j -> seq < wj -> seq && ! did_self ) { TAILQ_FOREACH ( p , & opp , tq ) add_param ( j , p , 0 , NULL ) ; did_self = 1 ; } if ( wild_jail_match ( j -> name , wj -> name ) ) TAILQ_FOREACH ( p , & wj -> params , tq ) add_param ( j , p , 0 , NULL ) ; } if ( ! did_self ) TAILQ_FOREACH ( p , & opp , tq ) add_param ( j , p , 0 , NULL ) ; pgen = 0 ; TAILQ_FOREACH ( p , & j -> params , tq ) { p -> gen = ++ pgen ; find_vars : TAILQ_FOREACH ( s , & p -> val , tq ) { while ( ( v = STAILQ_FIRST ( & s -> vars ) ) ) { TAILQ_FOREACH ( vp , & j -> params , tq ) if ( ! strcmp ( vp -> name , v -> name ) ) break ; if ( ! vp ) { jail_warnx ( j , " \" \" " , p -> name , v -> name ) ; bad_var : j -> flags |= JF_FAILED ; TAILQ_FOREACH ( vp , & j -> params , tq ) if ( vp -> gen == pgen ) vp -> flags |= PF_BAD ; goto free_var ; } if ( vp -> flags & PF_BAD ) goto bad_var ; if ( vp -> gen == pgen ) { jail_warnx ( j , " " , v -> name ) ; goto bad_var ; } TAILQ_FOREACH ( vs , & vp -> val , tq ) if ( ! STAILQ_EMPTY ( & vs -> vars ) ) { vp -> gen = pgen ; TAILQ_REMOVE ( & j -> params , vp , tq ) ; TAILQ_INSERT_BEFORE ( p , vp , tq ) ; p = vp ; goto find_vars ; } vs = TAILQ_FIRST ( & vp -> val ) ; if ( TAILQ_NEXT ( vs , tq ) != NULL && ( s -> s [ 0 ] != ' \0 ' || STAILQ_NEXT ( v , tq ) ) ) { jail_warnx ( j , " " " " , p -> name ) ; goto bad_var ; } s -> s = erealloc ( s -> s , s -> len + vs -> len + 1 ) ; memmove ( s -> s + v -> pos + vs -> len , s -> s + v -> pos , s -> len - v -> pos + 1 ) ; memcpy ( s -> s + v -> pos , vs -> s , vs -> len ) ; vv = v ; while ( ( vv = STAILQ_NEXT ( vv , tq ) ) ) vv -> pos += vs -> len ; s -> len += vs -> len ; while ( ( vs = TAILQ_NEXT ( vs , tq ) ) ) { ns = emalloc ( sizeof ( struct cfstring ) ) ; ns -> s = estrdup ( vs -> s ) ; ns -> len = vs -> len ; STAILQ_INIT ( & ns -> vars ) ; TAILQ_INSERT_AFTER ( & p -> val , s , ns , tq ) ; s = ns ; } free_var : free ( v -> name ) ; STAILQ_REMOVE_HEAD ( & s -> vars , tq ) ; free ( v ) ; } } } while ( ( p = TAILQ_FIRST ( & opp ) ) ) free_param ( & opp , p ) ; TAILQ_FOREACH_SAFE ( p , & j -> params , tq , tp ) if ( p -> flags & PF_VAR ) free_param ( & j -> params , p ) ; } while ( ( wj = TAILQ_FIRST ( & wild ) ) ) { free ( wj -> name ) ; while ( ( p = TAILQ_FIRST ( & wj -> params ) ) ) free_param ( & wj -> params , p ) ; TAILQ_REMOVE ( & wild , wj , tq ) ; } }
Parse the jail configuration file.
Parse the jail configuration file .
/* Separate the wildcard jails out from the actual jails. */ /* Set aside the jail's parameters. */ /*
		 * The jail name implies its "name" or "jid" parameter,
		 * though they may also be explicitly set later on.
		 */ /*
		 * Collect parameters for the jail, global parameters/variables,
		 * and any matching wildcard jails.
		 */ /* Resolve any variable substitutions. */ /* Free the jail's original parameter list and any variables. */