]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/jail.c
Makefile: Define TEST_STUB_ROOT in testsuite
[people/ms/pakfire.git] / src / libpakfire / jail.c
CommitLineData
fd37ccaf
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2022 Pakfire development team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
32d5f21d
MT
21#include <errno.h>
22#include <stdlib.h>
23
84bd7655 24#include <pakfire/logging.h>
fd37ccaf
MT
25#include <pakfire/jail.h>
26#include <pakfire/pakfire.h>
32d5f21d
MT
27#include <pakfire/util.h>
28
29#define ENVIRON_SIZE 128
fd37ccaf 30
d5bc8fe0
MT
31// The default environment that will be set for every command
32static const struct environ {
33 const char* key;
34 const char* val;
35} ENV[] = {
36 { "LANG", "en_US.utf-8" },
37 { "TERM", "vt100" },
38 { NULL, NULL },
39};
40
fd37ccaf
MT
41struct pakfire_jail {
42 struct pakfire* pakfire;
43 int nrefs;
32d5f21d 44
d639929b
MT
45 // Flags
46 int flags;
47
32d5f21d
MT
48 // Environment
49 char* env[ENVIRON_SIZE];
fd37ccaf
MT
50};
51
d5bc8fe0
MT
52static void pakfire_jail_free(struct pakfire_jail* jail) {
53 DEBUG(jail->pakfire, "Freeing jail at %p\n", jail);
54
55 // Free environment
56 for (unsigned int i = 0; jail->env[i]; i++)
57 free(jail->env[i]);
58
59 pakfire_unref(jail->pakfire);
60 free(jail);
61}
62
00ba1d9a
MT
63static int pakfire_jail_setup_interactive_env(struct pakfire_jail* jail) {
64 // Set PS1
65 int r = pakfire_jail_set_env(jail, "PS1", "pakfire-jail \\w> ");
66 if (r)
67 return r;
68
69 // Copy TERM
70 char* TERM = secure_getenv("TERM");
71 if (TERM) {
72 r = pakfire_jail_set_env(jail, "TERM", TERM);
73 if (r)
74 return r;
75 }
76
77 // Copy LANG
78 char* LANG = secure_getenv("LANG");
79 if (LANG) {
80 r = pakfire_jail_set_env(jail, "LANG", LANG);
81 if (r)
82 return r;
83 }
84
85 return 0;
86}
87
d639929b 88int pakfire_jail_create(struct pakfire_jail** jail, struct pakfire* pakfire, int flags) {
d5bc8fe0
MT
89 int r;
90
91 // Allocate a new jail
fd37ccaf
MT
92 struct pakfire_jail* j = calloc(1, sizeof(*j));
93 if (!j)
94 return 1;
95
96 // Reference Pakfire
97 j->pakfire = pakfire_ref(pakfire);
98
99 // Initialize reference counter
100 j->nrefs = 1;
101
d639929b
MT
102 // Store flags
103 j->flags = flags;
104
84bd7655
MT
105 DEBUG(j->pakfire, "Allocated new jail at %p\n", j);
106
d5bc8fe0
MT
107 // Set default environment
108 for (const struct environ* e = ENV; e->key; e++) {
109 r = pakfire_jail_set_env(j, e->key, e->val);
110 if (r)
111 goto ERROR;
112 }
113
00ba1d9a
MT
114 // Setup interactive stuff
115 if (j->flags & PAKFIRE_JAIL_INTERACTIVE) {
116 r = pakfire_jail_setup_interactive_env(j);
117 if (r)
118 goto ERROR;
119 }
120
fd37ccaf
MT
121 // Done
122 *jail = j;
123 return 0;
84bd7655 124
d5bc8fe0
MT
125ERROR:
126 pakfire_jail_free(j);
32d5f21d 127
d5bc8fe0 128 return r;
fd37ccaf
MT
129}
130
131struct pakfire_jail* pakfire_jail_ref(struct pakfire_jail* jail) {
132 ++jail->nrefs;
133
134 return jail;
135}
136
137struct pakfire_jail* pakfire_jail_unref(struct pakfire_jail* jail) {
138 if (--jail->nrefs > 0)
139 return jail;
140
141 pakfire_jail_free(jail);
142 return NULL;
143}
32d5f21d
MT
144
145// Environment
146
147// Returns the length of the environment
148static unsigned int pakfire_jail_env_length(struct pakfire_jail* jail) {
149 unsigned int i = 0;
150
151 // Count everything in the environment
152 for (char** e = jail->env; *e; e++)
153 i++;
154
155 return i;
156}
157
158// Finds an existing environment variable and returns its index or -1 if not found
159static int pakfire_jail_find_env(struct pakfire_jail* jail, const char* key) {
160 if (!key) {
161 errno = EINVAL;
162 return -1;
163 }
164
165 char buffer[strlen(key) + 2];
166 pakfire_string_format(buffer, "%s=", key);
167
168 for (unsigned int i = 0; jail->env[i]; i++) {
169 if (pakfire_string_startswith(jail->env[i], buffer))
170 return i;
171 }
172
173 // Nothing found
174 return -1;
175}
176
177// Returns the value of an environment variable or NULL
178const char* pakfire_jail_get_env(struct pakfire_jail* jail, const char* key) {
179 int i = pakfire_jail_find_env(jail, key);
180 if (i < 0)
181 return NULL;
182
183 return jail->env[i] + strlen(key) + 1;
184}
185
186// Sets an environment variable
187int pakfire_jail_set_env(struct pakfire_jail* jail, const char* key, const char* value) {
188 // Find the index where to write this value to
189 int i = pakfire_jail_find_env(jail, key);
190 if (i < 0)
191 i = pakfire_jail_env_length(jail);
192
193 // Return -ENOSPC when the environment is full
194 if (i >= ENVIRON_SIZE) {
195 errno = ENOSPC;
196 return -1;
197 }
198
199 // Free any previous value
200 if (jail->env[i])
201 free(jail->env[i]);
202
203 // Format and set environment variable
204 asprintf(&jail->env[i], "%s=%s", key, value);
205
206 DEBUG(jail->pakfire, "Set environment variable: %s\n", jail->env[i]);
207
208 return 0;
209}
9f50bf71
MT
210
211// Run a command in the jail
212int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[]) {
213 return 1; // TODO
214}