@push.rocks/smartdaemon 2.6.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.systemdservicedefinition.d.ts +11 -3
- package/dist_ts/classes.systemdservicedefinition.js +20 -10
- package/dist_ts/classes.systemdunit.d.ts +13 -0
- package/dist_ts/classes.systemdunit.js +54 -5
- package/dist_ts/classes.systemdunitfile.d.ts +8 -2
- package/dist_ts/classes.systemdunitfile.js +39 -12
- package/dist_ts/smartdaemon.plugins.d.ts +2 -1
- package/dist_ts/smartdaemon.plugins.js +3 -2
- package/dist_ts/systemd.definition.d.ts +2 -2
- package/dist_ts/systemd.definition.js +8 -4
- package/package.json +5 -5
- package/readme.md +70 -7
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.systemdservicedefinition.ts +29 -15
- package/ts/classes.systemdunit.ts +63 -4
- package/ts/classes.systemdunitfile.ts +46 -15
- package/ts/smartdaemon.plugins.ts +2 -1
- package/ts/systemd.definition.ts +8 -4
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartdaemon',
|
|
6
|
-
version: '2.
|
|
6
|
+
version: '2.7.1',
|
|
7
7
|
description: 'Start scripts as long running daemons and manage them.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHdEQUF3RDtDQUN0RSxDQUFBIn0=
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { type ISystemdServiceStartup, type ISystemdServiceDependencies, type ISystemdServiceInstallTargets } from './systemd.definition.js';
|
|
2
2
|
export type { ISystemdServiceStartup, ISystemdServiceDependencies, ISystemdServiceInstallTargets } from './systemd.definition.js';
|
|
3
|
-
|
|
3
|
+
interface ISystemdServiceDefinitionBaseOptions {
|
|
4
4
|
unitName: string;
|
|
5
5
|
description: string;
|
|
6
6
|
executable: string;
|
|
7
7
|
args: readonly string[];
|
|
8
8
|
workingDirectory: string;
|
|
9
|
-
user: string;
|
|
10
|
-
group: string;
|
|
11
9
|
restart: 'no' | 'on-failure' | 'always';
|
|
12
10
|
killMode: 'mixed' | 'control-group';
|
|
13
11
|
timeoutStopSeconds: number;
|
|
@@ -15,12 +13,22 @@ export interface ISystemdServiceDefinitionOptions {
|
|
|
15
13
|
dependencies?: ISystemdServiceDependencies;
|
|
16
14
|
install?: ISystemdServiceInstallTargets;
|
|
17
15
|
}
|
|
16
|
+
export type ISystemdServiceDefinitionOptions = ISystemdServiceDefinitionBaseOptions & ({
|
|
17
|
+
scope?: 'system';
|
|
18
|
+
user: string;
|
|
19
|
+
group: string;
|
|
20
|
+
} | {
|
|
21
|
+
scope: 'user';
|
|
22
|
+
user?: never;
|
|
23
|
+
group?: never;
|
|
24
|
+
});
|
|
18
25
|
export declare class SystemdServiceDefinitionError extends Error {
|
|
19
26
|
constructor();
|
|
20
27
|
}
|
|
21
28
|
/** Literal direct-execution definition; never introduces a shell or environment expansion. */
|
|
22
29
|
export declare class SystemdServiceDefinition {
|
|
23
30
|
readonly unitName: string;
|
|
31
|
+
readonly scope: 'system' | 'user';
|
|
24
32
|
readonly content: string;
|
|
25
33
|
readonly sha256: string;
|
|
26
34
|
constructor(options: ISystemdServiceDefinitionOptions);
|
|
@@ -13,6 +13,16 @@ export class SystemdServiceDefinition {
|
|
|
13
13
|
if (!value)
|
|
14
14
|
throw new SystemdServiceDefinitionError();
|
|
15
15
|
};
|
|
16
|
+
requireValue(options && !plugins.util.types.isProxy(options) &&
|
|
17
|
+
Object.getPrototypeOf(options) === Object.prototype);
|
|
18
|
+
const scopeDescriptor = Object.getOwnPropertyDescriptor(options, 'scope');
|
|
19
|
+
requireValue(scopeDescriptor === undefined ||
|
|
20
|
+
scopeDescriptor.enumerable && 'value' in scopeDescriptor);
|
|
21
|
+
const scopeValue = scopeDescriptor?.value ?? 'system';
|
|
22
|
+
if (scopeValue !== 'system' && scopeValue !== 'user') {
|
|
23
|
+
throw new SystemdServiceDefinitionError();
|
|
24
|
+
}
|
|
25
|
+
const scope = scopeValue;
|
|
16
26
|
const text = (value, maximum = 4096) => typeof value === 'string' && value.length <= maximum && !/[\x00-\x1f\x7f]/.test(value) &&
|
|
17
27
|
!/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u.test(value);
|
|
18
28
|
const absolute = (value) => text(value) && plugins.path.isAbsolute(value) &&
|
|
@@ -23,15 +33,13 @@ export class SystemdServiceDefinition {
|
|
|
23
33
|
'executable',
|
|
24
34
|
'args',
|
|
25
35
|
'workingDirectory',
|
|
26
|
-
'user',
|
|
27
|
-
'group',
|
|
28
36
|
'restart',
|
|
29
37
|
'killMode',
|
|
30
38
|
'timeoutStopSeconds',
|
|
39
|
+
...(scope === 'system' ? ['user', 'group'] : []),
|
|
31
40
|
];
|
|
32
|
-
requireValue(
|
|
33
|
-
|
|
34
|
-
&& Object.getOwnPropertyDescriptor(options, key)?.enumerable && 'value' in Object.getOwnPropertyDescriptor(options, key)) && keys.every((key) => {
|
|
41
|
+
requireValue(Reflect.ownKeys(options).every(key => typeof key === 'string' && [...keys, 'scope', 'startup', 'dependencies', 'install'].includes(key)
|
|
42
|
+
&& Object.getOwnPropertyDescriptor(options, key)?.enumerable && 'value' in Object.getOwnPropertyDescriptor(options, key)) && keys.every((key) => {
|
|
35
43
|
const descriptor = Object.getOwnPropertyDescriptor(options, key);
|
|
36
44
|
return descriptor && 'value' in descriptor;
|
|
37
45
|
}));
|
|
@@ -49,7 +57,9 @@ export class SystemdServiceDefinition {
|
|
|
49
57
|
Reflect.ownKeys(options.args).length === options.args.length + 1 &&
|
|
50
58
|
Array.from({ length: options.args.length }, (_, index) => Object.getOwnPropertyDescriptor(options.args, String(index)))
|
|
51
59
|
.every((descriptor) => descriptor && 'value' in descriptor && text(descriptor.value)));
|
|
52
|
-
|
|
60
|
+
if (scope === 'system') {
|
|
61
|
+
requireValue([options.user, options.group].every((value) => typeof value === 'string' && /^[a-zA-Z_][a-zA-Z0-9_-]{0,63}$/.test(value)));
|
|
62
|
+
}
|
|
53
63
|
requireValue(['no', 'on-failure', 'always'].includes(options.restart) &&
|
|
54
64
|
['mixed', 'control-group'].includes(options.killMode) &&
|
|
55
65
|
Number.isSafeInteger(options.timeoutStopSeconds) &&
|
|
@@ -59,8 +69,9 @@ export class SystemdServiceDefinition {
|
|
|
59
69
|
.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll('%', '%%')
|
|
60
70
|
.replaceAll('$', () => command ? '$$' : '$') +
|
|
61
71
|
'"';
|
|
62
|
-
const relations = renderServiceRelations(options, options.unitName, options.restart, () => { throw new SystemdServiceDefinitionError(); });
|
|
72
|
+
const relations = renderServiceRelations(options, options.unitName, options.restart, scope, () => { throw new SystemdServiceDefinitionError(); });
|
|
63
73
|
this.unitName = options.unitName;
|
|
74
|
+
this.scope = scope;
|
|
64
75
|
this.content = [
|
|
65
76
|
'[Unit]',
|
|
66
77
|
`Description=${options.description.replaceAll('%', '%%')}`,
|
|
@@ -68,8 +79,7 @@ export class SystemdServiceDefinition {
|
|
|
68
79
|
'',
|
|
69
80
|
'[Service]',
|
|
70
81
|
...relations.service,
|
|
71
|
-
`User=${options.user}`,
|
|
72
|
-
`Group=${options.group}`,
|
|
82
|
+
...(scope === 'system' ? [`User=${options.user}`, `Group=${options.group}`] : []),
|
|
73
83
|
`ExecStart=${[quote(options.executable), ...options.args.map((value) => quote(value, true))].join(' ')}`,
|
|
74
84
|
// WorkingDirectory is a raw path value, not an ExecStart word list.
|
|
75
85
|
`WorkingDirectory=${options.workingDirectory.replaceAll('%', '%%')}`,
|
|
@@ -93,4 +103,4 @@ export class SystemdServiceDefinition {
|
|
|
93
103
|
Object.freeze(this);
|
|
94
104
|
}
|
|
95
105
|
}
|
|
96
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
106
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zeXN0ZW1kc2VydmljZWRlZmluaXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnN5c3RlbWRzZXJ2aWNlZGVmaW5pdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxzQkFBc0IsRUFDTyxNQUFNLHlCQUF5QixDQUFDO0FBc0J0RSxNQUFNLE9BQU8sNkJBQThCLFNBQVEsS0FBSztJQUN0RDtRQUNFLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxJQUFJLEdBQUcsK0JBQStCLENBQUM7SUFDOUMsQ0FBQztDQUNGO0FBRUQsOEZBQThGO0FBQzlGLE1BQU0sT0FBTyx3QkFBd0I7SUFNbkMsWUFBWSxPQUF5QztRQUNuRCxNQUFNLFlBQVksR0FBRyxDQUFDLEtBQWMsRUFBUSxFQUFFO1lBQzVDLElBQUksQ0FBQyxLQUFLO2dCQUFFLE1BQU0sSUFBSSw2QkFBNkIsRUFBRSxDQUFDO1FBQ3hELENBQUMsQ0FBQztRQUNGLFlBQVksQ0FBQyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO1lBQzFELE1BQU0sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLEtBQUssTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUUsWUFBWSxDQUFDLGVBQWUsS0FBSyxTQUFTO1lBQ3hDLGVBQWUsQ0FBQyxVQUFVLElBQUksT0FBTyxJQUFJLGVBQWUsQ0FBQyxDQUFDO1FBQzVELE1BQU0sVUFBVSxHQUFZLGVBQWUsRUFBRSxLQUFLLElBQUksUUFBUSxDQUFDO1FBQy9ELElBQUksVUFBVSxLQUFLLFFBQVEsSUFB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
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export interface ISystemdUnitOptions {
|
|
2
2
|
unitName: string;
|
|
3
|
+
/** Defaults to the system manager. User scope addresses the calling user's manager only. */
|
|
4
|
+
scope?: 'system' | 'user';
|
|
5
|
+
/**
|
|
6
|
+
* User-manager socket directory. Defaults to a non-empty XDG_RUNTIME_DIR. May be absent at
|
|
7
|
+
* construction; every call that contacts the user manager then refuses with `invalid_options`.
|
|
8
|
+
*/
|
|
9
|
+
runtimeDirectory?: string;
|
|
3
10
|
/** Absolute executable path supplied by trusted owning code. */
|
|
4
11
|
systemctlPath?: string;
|
|
5
12
|
/** Bounds the systemctl client, not the server-side job. Defaults to 120 seconds. */
|
|
@@ -44,6 +51,11 @@ export declare class SystemdUnit {
|
|
|
44
51
|
private readonly unitName;
|
|
45
52
|
private readonly executable;
|
|
46
53
|
private readonly timeout;
|
|
54
|
+
private readonly scope;
|
|
55
|
+
private readonly runtimeDirectory?;
|
|
56
|
+
private readonly homeDirectory?;
|
|
57
|
+
private readonly configDirectory?;
|
|
58
|
+
private readonly dataDirectory?;
|
|
47
59
|
constructor(optionsArg: ISystemdUnitOptions);
|
|
48
60
|
/** Snapshot only. Callers own application-specific admission and restart policy. */
|
|
49
61
|
inspect(): Promise<ISystemdUnitState>;
|
|
@@ -60,5 +72,6 @@ export declare class SystemdUnit {
|
|
|
60
72
|
inspectConfiguration(): Promise<ISystemdUnitConfigurationState>;
|
|
61
73
|
/** Reloads unit definitions globally; does not enable, unmask, start or stop a unit. */
|
|
62
74
|
reloadConfiguration(): Promise<ISystemdUnitConfigurationState>;
|
|
75
|
+
private validateUserRuntime;
|
|
63
76
|
private command;
|
|
64
77
|
}
|
|
@@ -24,11 +24,32 @@ export class SystemdUnit {
|
|
|
24
24
|
this.unitName = optionsArg?.unitName;
|
|
25
25
|
this.executable = optionsArg?.systemctlPath ?? '/usr/bin/systemctl';
|
|
26
26
|
this.timeout = optionsArg?.commandTimeoutMs ?? 120000;
|
|
27
|
+
this.scope = optionsArg?.scope ?? 'system';
|
|
28
|
+
// An empty XDG_RUNTIME_DIR counts as unset, like the sibling XDG variables below. An explicit
|
|
29
|
+
// option is never reinterpreted, so an empty or relative option stays malformed.
|
|
30
|
+
this.runtimeDirectory = this.scope === 'user'
|
|
31
|
+
? optionsArg?.runtimeDirectory ?? (process.env.XDG_RUNTIME_DIR || undefined) : undefined;
|
|
32
|
+
this.homeDirectory = this.scope === 'user' ? plugins.os.userInfo().homedir : undefined;
|
|
33
|
+
this.configDirectory = this.scope === 'user' ? process.env.XDG_CONFIG_HOME || undefined : undefined;
|
|
34
|
+
this.dataDirectory = this.scope === 'user' ? process.env.XDG_DATA_HOME || undefined : undefined;
|
|
35
|
+
const safeDirectory = (value) => typeof value === 'string' && value !== '/' && plugins.path.isAbsolute(value) &&
|
|
36
|
+
plugins.path.normalize(value) === value && !value.endsWith('/') &&
|
|
37
|
+
value.length <= 4000 && !/[\x00-\x1f\x7f]/.test(value);
|
|
38
|
+
// Only a supplied runtime directory is validated here. Its absence matters solely to calls that
|
|
39
|
+
// reach the user manager, and those refuse it in validateUserRuntime(). Admitting absence lets
|
|
40
|
+
// owners read protected unit files from contexts without a login session (cron, plain ssh).
|
|
27
41
|
if (typeof this.unitName !== 'string' ||
|
|
28
42
|
!/^[a-zA-Z0-9][a-zA-Z0-9_.:@-]{0,230}\.service$/.test(this.unitName) ||
|
|
29
43
|
typeof this.executable !== 'string' || !plugins.path.isAbsolute(this.executable) ||
|
|
30
44
|
this.executable.includes('\0') || !Number.isSafeInteger(this.timeout) ||
|
|
31
|
-
this.timeout < 1 || this.timeout > 600000
|
|
45
|
+
this.timeout < 1 || this.timeout > 600000 ||
|
|
46
|
+
!['system', 'user'].includes(this.scope) ||
|
|
47
|
+
(this.scope === 'system' && optionsArg?.runtimeDirectory !== undefined) ||
|
|
48
|
+
(this.scope === 'user' &&
|
|
49
|
+
(this.runtimeDirectory !== undefined && !safeDirectory(this.runtimeDirectory) ||
|
|
50
|
+
!safeDirectory(this.homeDirectory) ||
|
|
51
|
+
this.configDirectory !== undefined && !safeDirectory(this.configDirectory) ||
|
|
52
|
+
this.dataDirectory !== undefined && !safeDirectory(this.dataDirectory))))
|
|
32
53
|
throw new SystemdUnitError('invalid_options');
|
|
33
54
|
}
|
|
34
55
|
/** Snapshot only. Callers own application-specific admission and restart policy. */
|
|
@@ -137,15 +158,43 @@ export class SystemdUnit {
|
|
|
137
158
|
await this.command(['daemon-reload']);
|
|
138
159
|
return this.inspectConfiguration();
|
|
139
160
|
}
|
|
140
|
-
|
|
161
|
+
async validateUserRuntime() {
|
|
162
|
+
if (this.scope !== 'user')
|
|
163
|
+
return;
|
|
164
|
+
// Runs before every systemctl invocation, so a missing directory refuses without side effects.
|
|
165
|
+
const runtimeDirectory = this.runtimeDirectory;
|
|
166
|
+
if (runtimeDirectory === undefined)
|
|
167
|
+
throw new SystemdUnitError('invalid_options');
|
|
168
|
+
try {
|
|
169
|
+
const uid = process.getuid?.();
|
|
170
|
+
if (process.platform !== 'linux' || uid === undefined || process.geteuid?.() !== uid ||
|
|
171
|
+
await plugins.fs.realpath(runtimeDirectory) !== runtimeDirectory) {
|
|
172
|
+
throw new SystemdUnitError('invalid_options');
|
|
173
|
+
}
|
|
174
|
+
const info = await plugins.fs.lstat(runtimeDirectory);
|
|
175
|
+
if (!info.isDirectory() || info.isSymbolicLink() || info.uid !== uid ||
|
|
176
|
+
(info.mode & 0o077) !== 0)
|
|
177
|
+
throw new SystemdUnitError('invalid_options');
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
throw new SystemdUnitError('invalid_options');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async command(argsArg) {
|
|
184
|
+
await this.validateUserRuntime();
|
|
141
185
|
return new Promise((resolve, reject) => {
|
|
142
|
-
plugins.childProcess.execFile(this.executable, ['--system', '--no-ask-password', '--no-pager', ...argsArg], {
|
|
186
|
+
plugins.childProcess.execFile(this.executable, [this.scope === 'user' ? '--user' : '--system', '--no-ask-password', '--no-pager', ...argsArg], {
|
|
143
187
|
encoding: 'utf8',
|
|
144
188
|
timeout: this.timeout,
|
|
145
189
|
killSignal: 'SIGKILL',
|
|
146
190
|
maxBuffer: 16384,
|
|
147
191
|
windowsHide: true,
|
|
148
|
-
env:
|
|
192
|
+
env: this.scope === 'user'
|
|
193
|
+
? { PATH: '/usr/bin:/bin', LANG: 'C', LC_ALL: 'C',
|
|
194
|
+
HOME: this.homeDirectory, XDG_RUNTIME_DIR: this.runtimeDirectory,
|
|
195
|
+
...(this.configDirectory ? { XDG_CONFIG_HOME: this.configDirectory } : {}),
|
|
196
|
+
...(this.dataDirectory ? { XDG_DATA_HOME: this.dataDirectory } : {}) }
|
|
197
|
+
: { PATH: '/usr/bin:/bin', LANG: 'C', LC_ALL: 'C' },
|
|
149
198
|
}, (error, stdout) => {
|
|
150
199
|
// execFile settles after the client closes. A timed-out client's remote job may continue.
|
|
151
200
|
if (error)
|
|
@@ -156,4 +205,4 @@ export class SystemdUnit {
|
|
|
156
205
|
});
|
|
157
206
|
}
|
|
158
207
|
}
|
|
159
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zeXN0ZW1kdW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuc3lzdGVtZHVuaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSwwQkFBMEIsQ0FBQztBQTJDcEQsTUFBTSxPQUFPLGdCQUFpQixTQUFRLEtBQUs7SUFDekMsWUFBNEIsSUFBNEQ7UUFDdEYsS0FBSyxDQUFDLGtDQUFrQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBRHZCLFNBQUksR0FBSixJQUFJLENBQXdEO1FBRXRGLElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBRUQsTUFBTSxVQUFVLEdBQUc7SUFDakIsSUFBSTtJQUNKLFdBQVc7SUFDWCxhQUFhO0lBQ2IsVUFBVTtJQUNWLGVBQWU7SUFDZixTQUFTO0lBQ1QsWUFBWTtJQUNaLGNBQWM7SUFDZCxVQUFVO0lBQ1YsS0FBSztDQUNHLENBQUM7QUFFWCxrR0FBa0c7QUFDbEcsTUFBTSxPQUFPLFdBQVc7SUFLdEIsWUFBWSxVQUErQjtRQUN6QyxJQUFJLENBQUMsUUFBUSxHQUFHLFVBQVUsRUFBRSxRQUFRLENBQUM7UUFDckMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLEVBQUUsYUFBYSxJQUFJLG9CQUFvQixDQUFDO1FBQ3BFLElBQUksQ0FBQyxPQUFPLEdBQUcsVUFBVSxFQUFFLGdCQUFnQixJQUFJLE1BQU0sQ0FBQztRQUN0RCxJQUNFLE9BQU8sSUFBSSxDQUFDLFFBQVEsS0FBSyxRQUFRO1lBQ2pDLENBQUMsK0NBQStDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7WUFDcEUsT0FBTyxJQUFJLENBQUMsVUFBVSxLQUFLLFFBQVEsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7WUFDaEYsSUFBSSxDQUFDLFVBQVUsQ0FBQyxR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
|
|
208
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zeXN0ZW1kdW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuc3lzdGVtZHVuaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSwwQkFBMEIsQ0FBQztBQWtEcEQsTUFBTSxPQUFPLGdCQUFpQixTQUFRLEtBQUs7SUFDekMsWUFBNEIsSUFBNEQ7UUFDdEYsS0FBSyxDQUFDLGtDQUFrQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBRHZCLFNBQUksR0FBSixJQUFJLENBQXdEO1FBRXRGLElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBRUQsTUFBTSxVQUFVLEdBQUc7SUFDakIsSUFBSTtJQUNKLFdBQVc7SUFDWCxhQUFhO0lBQ2IsVUFBVTtJQUNWLGVBQWU7SUFDZixTQUFTO0lBQ1QsWUFBWTtJQUNaLGNBQWM7SUFDZCxVQUFVO0lBQ1YsS0FBSztDQUNHLENBQUM7QUFFWCxrR0FBa0c7QUFDbEcsTUFBTSxPQUFPLFdBQVc7SUFVdEIsWUFBWSxVQUErQjtRQUN6QyxJQUFJLENBQUMsUUFBUSxHQUFHLFVBQVUsRUFBRSxRQUFRLENBQUM7UUFDckMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLEVBQUUsYUFBYSxJQUFJLG9CQUFvQixDQUFDO1FBQ3BFLElBQUksQ0FBQyxPQUFPLEdBQUcsVUFBVSxFQUFFLGdCQUFnQixJQUFJLE1BQU0sQ0FBQztRQUN0RCxJQUFJLENBQUMsS0FBSyxHQUFHLFVBQVUsRUFBRSxLQUFLLElBQUksUUFBUSxDQUFDO1FBQzNDLDhGQUE4RjtRQUM5RixpRkFBaUY7UUFDakYsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxLQUFLLEtBQUssTUFBTTtZQUMzQyxDQUFDLENBQUMsVUFBVSxFQUFFLGdCQUFnQixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksU0FBUyxDQUFD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
|
|
@@ -3,7 +3,7 @@ import { type ISystemdUnitOptions } from './classes.systemdunit.js';
|
|
|
3
3
|
export interface ISystemdUnitFileOptions extends ISystemdUnitOptions {
|
|
4
4
|
/** Local vendor definitions can be installed without removing an administrator's mask. */
|
|
5
5
|
unitDirectory?: string;
|
|
6
|
-
/** Trusted owning-code qualification only. Defaults to root. */
|
|
6
|
+
/** Trusted owning-code qualification only. Defaults to root for system, current uid for user. */
|
|
7
7
|
expectedUid?: number;
|
|
8
8
|
}
|
|
9
9
|
export interface ISystemdUnitFileRecord {
|
|
@@ -22,11 +22,17 @@ export declare class SystemdUnitFile {
|
|
|
22
22
|
readonly path: string;
|
|
23
23
|
private readonly directory;
|
|
24
24
|
private readonly uid;
|
|
25
|
+
private readonly scope;
|
|
26
|
+
private readonly configDirectory?;
|
|
27
|
+
private readonly runtimeDirectory?;
|
|
25
28
|
private readonly unit;
|
|
26
29
|
private readonly name;
|
|
27
30
|
private busy;
|
|
28
31
|
constructor(options: ISystemdUnitFileOptions);
|
|
29
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Reads only the exact protected definition; no systemd or filesystem mutation.
|
|
34
|
+
* Needs no user-manager runtime directory.
|
|
35
|
+
*/
|
|
30
36
|
inspect(): Promise<ISystemdUnitFileRecord | null>;
|
|
31
37
|
/**
|
|
32
38
|
* Expected previous digest is mandatory; null admits an absent file. Exact desired bytes are idempotent.
|
|
@@ -29,16 +29,34 @@ export class SystemdUnitFile {
|
|
|
29
29
|
this.busy = false;
|
|
30
30
|
this.unit = new SystemdUnit(options);
|
|
31
31
|
this.name = options.unitName;
|
|
32
|
-
this.
|
|
33
|
-
this.
|
|
34
|
-
|
|
35
|
-
plugins.path.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
this.scope = options.scope ?? 'system';
|
|
33
|
+
const home = this.scope === 'user' ? plugins.os.userInfo().homedir : undefined;
|
|
34
|
+
const dataDirectory = this.scope === 'user'
|
|
35
|
+
? process.env.XDG_DATA_HOME || plugins.path.join(home, '.local/share') : undefined;
|
|
36
|
+
this.configDirectory = this.scope === 'user'
|
|
37
|
+
? process.env.XDG_CONFIG_HOME || plugins.path.join(home, '.config') : undefined;
|
|
38
|
+
// Resolved exactly as SystemdUnit resolves it, so both agree on presence.
|
|
39
|
+
this.runtimeDirectory = this.scope === 'user'
|
|
40
|
+
? options.runtimeDirectory ?? (process.env.XDG_RUNTIME_DIR || undefined) : undefined;
|
|
41
|
+
this.directory = options.unitDirectory ?? (this.scope === 'user'
|
|
42
|
+
? plugins.path.join(dataDirectory, 'systemd/user') : '/usr/local/lib/systemd/system');
|
|
43
|
+
this.uid = options.expectedUid ?? (this.scope === 'user' ? process.getuid?.() ?? -1 : 0);
|
|
44
|
+
const validDirectory = (directory) => typeof directory === 'string' && directory !== '/' &&
|
|
45
|
+
plugins.path.isAbsolute(directory) && plugins.path.normalize(directory) === directory &&
|
|
46
|
+
!directory.endsWith('/') && !/[\x00-\x1f\x7f]/.test(directory) &&
|
|
47
|
+
directory.length <= 4000;
|
|
48
|
+
requireValue(validDirectory(this.directory) && Number.isSafeInteger(this.uid) && this.uid >= 0 &&
|
|
49
|
+
(this.scope === 'system' ||
|
|
50
|
+
this.uid === process.getuid?.() && validDirectory(this.configDirectory) &&
|
|
51
|
+
// inspect() reads only the unit directory, so an absent runtime directory is refused
|
|
52
|
+
// later, by install(); a supplied one must still be well formed.
|
|
53
|
+
(this.runtimeDirectory === undefined || validDirectory(this.runtimeDirectory))), 'invalid_options');
|
|
39
54
|
this.path = plugins.path.join(this.directory, this.name);
|
|
40
55
|
}
|
|
41
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Reads only the exact protected definition; no systemd or filesystem mutation.
|
|
58
|
+
* Needs no user-manager runtime directory.
|
|
59
|
+
*/
|
|
42
60
|
async inspect() {
|
|
43
61
|
if (!await this.directories(false))
|
|
44
62
|
return null;
|
|
@@ -51,8 +69,13 @@ export class SystemdUnitFile {
|
|
|
51
69
|
*/
|
|
52
70
|
async install(definition, expectedSha256) {
|
|
53
71
|
requireValue(definition instanceof SystemdServiceDefinition && definition.unitName === this.name &&
|
|
72
|
+
definition.scope === this.scope &&
|
|
54
73
|
(expectedSha256 === null ||
|
|
55
|
-
typeof expectedSha256 === 'string' && /^[a-f0-9]{64}$/.test(expectedSha256))
|
|
74
|
+
typeof expectedSha256 === 'string' && /^[a-f0-9]{64}$/.test(expectedSha256)) &&
|
|
75
|
+
// Installation admits, reloads and verifies through the user manager and recognizes its
|
|
76
|
+
// runtime mask path. Refusing here, before the busy latch and any directory or systemctl
|
|
77
|
+
// effect, keeps the local error code instead of a wrapped write_failed.
|
|
78
|
+
(this.scope === 'system' || this.runtimeDirectory !== undefined), 'invalid_options');
|
|
56
79
|
requireValue(!this.busy, 'busy');
|
|
57
80
|
this.busy = true;
|
|
58
81
|
let temporary;
|
|
@@ -138,11 +161,15 @@ export class SystemdUnitFile {
|
|
|
138
161
|
['enabled', 'enabled-runtime', 'disabled'].includes(state.unitFileState) ||
|
|
139
162
|
state.loadState === 'not-found' && state.unitFileState === ''), 'unsafe_unit');
|
|
140
163
|
const configuration = await this.unit.inspectConfiguration();
|
|
141
|
-
const
|
|
164
|
+
const maskPaths = this.scope === 'system'
|
|
165
|
+
? [plugins.path.join(state.unitFileState === 'masked-runtime' ? '/run/systemd/system' : '/etc/systemd/system', this.name)]
|
|
166
|
+
: (state.unitFileState === 'masked-runtime'
|
|
167
|
+
? [this.runtimeDirectory, '/run'].map(root => plugins.path.join(root, 'systemd/user', this.name))
|
|
168
|
+
: [this.configDirectory, '/etc'].map(root => plugins.path.join(root, 'systemd/user', this.name)));
|
|
142
169
|
requireValue(!configuration.needsReload && configuration.dropInPaths === '' &&
|
|
143
170
|
(masked(state)
|
|
144
171
|
? configuration.fragmentPath !== this.path &&
|
|
145
|
-
['/dev/null',
|
|
172
|
+
['/dev/null', ...maskPaths].includes(configuration.fragmentPath)
|
|
146
173
|
: configuration.fragmentPath === (state.loadState === 'not-found' ? '' : this.path)), 'unsafe_unit');
|
|
147
174
|
return configuration;
|
|
148
175
|
}
|
|
@@ -246,4 +273,4 @@ export class SystemdUnitFile {
|
|
|
246
273
|
}
|
|
247
274
|
}
|
|
248
275
|
}
|
|
249
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zeXN0ZW1kdW5pdGZpbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnN5c3RlbWR1bml0ZmlsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ2pGLE9BQU8sRUFJTCxXQUFXLEdBQ1osTUFBTSwwQkFBMEIsQ0FBQztBQVlsQyxNQUFNLE9BQU8sb0JBQXFCLFNBQVEsS0FBSztJQUM3QyxZQUNrQixJQU9HO1FBRW5CLEtBQUssQ0FBQyxnREFBZ0QsSUFBSSxHQUFHLENBQUMsQ0FBQztRQVQvQyxTQUFJLEdBQUosSUFBSSxDQU9EO1FBR25CLElBQUksQ0FBQyxJQUFJLEdBQUcsc0JBQXNCLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBQ0QsTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFjLEVBQUUsSUFBa0MsRUFBUSxFQUFFO0lBQ2hGLElBQUksQ0FBQyxLQUFLO1FBQUUsTUFBTSxJQUFJLG9CQUFvQixDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ25ELENBQUMsQ0FBQztBQUNGLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FBaUIsRUFBRSxFQUFFLENBQ25DLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDbEUsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUF3QixFQUFFLEVBQUUsQ0FDekMsS0FBSyxDQUFDLE9BQU8sS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLFVBQVUsS0FBSyxDQUFDO0lBQzdDLEtBQUssQ0FBQyxZQUFZLEtBQUssRUFBRSxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssRUFBRTtJQUM3QyxDQUFDLEtBQUssQ0FBQyxXQUFXLEtBQUss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
|
|
276
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zeXN0ZW1kdW5pdGZpbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnN5c3RlbWR1bml0ZmlsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ2pGLE9BQU8sRUFJTCxXQUFXLEdBQ1osTUFBTSwwQkFBMEIsQ0FBQztBQVlsQyxNQUFNLE9BQU8sb0JBQXFCLFNBQVEsS0FBSztJQUM3QyxZQUNrQixJQU9HO1FBRW5CLEtBQUssQ0FBQyxnREFBZ0QsSUFBSSxHQUFHLENBQUMsQ0FBQztRQVQvQyxTQUFJLEdBQUosSUFBSSxDQU9EO1FBR25CLElBQUksQ0FBQyxJQUFJLEdBQUcsc0JBQXNCLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBQ0QsTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFjLEVBQUUsSUFBa0MsRUFBUSxFQUFFO0lBQ2hGLElBQUksQ0FBQyxLQUFLO1FBQUUsTUFBTSxJQUFJLG9CQUFvQixDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ25ELENBQUMsQ0FBQztBQUNGLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FBaUIsRUFBRSxFQUFFLENBQ25DLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDbEUsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUF3QixFQUFFLEVBQUUsQ0FDekMsS0FBSyxDQUFDLE9BQU8sS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLFVBQVUsS0FBSyxDQUFDO0lBQzdDLEtBQUssQ0FBQyxZQUFZLEtBQUssRUFBRSxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssRUFBRTtJQUM3QyxDQUFDLEtBQUssQ0FBQyxXQUFXLEtBQUssVUFBVSxJQUFJLEtBQUssQ0FBQyxRQUFRLEtBQUssTUFBTTtRQUM1RCxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDO0FBQ25FLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FBd0IsRUFBRSxFQUFFLENBQzFDLEtBQUssQ0FBQyxTQUFTLEtBQUssUUFBUTtJQUM1QixDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDN0QsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFrQyxFQUFFLEtBQW1DLEVBQUUsRUFBRSxDQUMzRixJQUFJLENBQUMsR0FBRyxLQUFLLEtBQUssQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxLQUFLLENBQUMsR0FBRyxDQUFDO0FBRW5EOzs7R0FHRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBVzFCLFlBQVksT0FBZ0M7UUFGcEMsU0FBSSxHQUFHLEtBQUssQ0FBQztRQUduQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUM3QixJQUFJLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksUUFBUSxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQy9FLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxLQUFLLEtBQUssTUFBTTtZQUN6QyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDdEYsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsS0FBSyxLQUFLLE1BQU07WUFDMUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUssRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ25GLDBFQUEwRTtRQUMxRSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEtBQUssS0FBSyxNQUFNO1lBQzNDLENBQUMsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ3ZGLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGFBQWEsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssTUFBTTtZQUM5RCxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBQ3pGLElBQUksQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekYsTUFBTSxjQUFjLEdBQUcsQ0FBQyxTQUFrQixFQUF1QixFQUFFLENBQ2pFLE9BQU8sU0FBUyxLQUFLLFFBQVEsSUFBSSxTQUFTLEtBQUssR0FBRztZQUNoRCxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsS0FBSyxTQUFTO1lBQ3JGLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDOUQsU0FBUyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUM7UUFDN0IsWUFBWSxDQUNWLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDO1lBQy9FLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxRQUFRO2dCQUN0QixJQUFJLENBQUMsR0FBRyxLQUFLLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO29CQUN2RSxxRkFBcUY7b0JBQ3JGLGlFQUFpRTtvQkFDakUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEtBQUssU0FBUyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEVBQ25GLGlCQUFpQixDQUNsQixDQUFDO1FBQ0YsSUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLE9BQU87UUFDbEIsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQztRQUNoRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3hDLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDdEYsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxPQUFPLENBQ2xCLFVBQW9DLEVBQ3BDLGNBQTZCO1FBRTdCLFlBQVksQ0FDVixVQUFVLFlBQVksd0JBQXdCLElBQUksVUFBVSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsSUFBSTtZQUNqRixVQUFVLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxLQUFLO1lBQy9CLENBQUMsY0FBYyxLQUFLLElBQUk7Z0JBQ3RCLE9BQU8sY0FBYyxLQUFLLFFBQVEsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDOUUsd0ZBQXdGO1lBQ3hGLHlGQUF5RjtZQUN6Rix3RUFBd0U7WUFDeEUsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLFFBQVEsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEtBQUssU0FBUyxDQUFDLEVBQ2xFLGlCQUFpQixDQUNsQixDQUFDO1FBQ0YsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLFNBQTZCLENBQUM7UUFDbEMsSUFBSSxhQUF3QyxDQUFDO1FBQzdDLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QyxNQUFNLG1CQUFtQixHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNyRCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDN0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1QyxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUM3RCxNQUFNLE9BQU8sR0FBRyxXQUFXLEtBQUssVUFBVSxDQUFDLE1BQU0sQ0FBQztZQUNsRCxZQUFZLENBQUMsQ0FBQyxPQUFPLElBQUksV0FBVyxLQUFLLGNBQWMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNwRSxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLElBQUksUUFBUSxFQUFFLENBQUM7b0JBQ2IsTUFBTSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxhQUFhLFdBQVcsRUFBRSxDQUFDO29CQUN0RCxJQUFJLENBQUM7d0JBQ0gsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQzVDLENBQUM7b0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQzt3QkFDZixJQUFLLEtBQStCLENBQUMsSUFBSSxLQUFLLFFBQVE7NEJBQUUsTUFBTSxLQUFLLENBQUM7d0JBQ3BFLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUM7b0JBQ3BGLENBQUM7b0JBQ0QsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNwQyxDQUFDO2dCQUNELFNBQVMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FDM0IsSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUNuRCxDQUFDO2dCQUNGLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDOUQsYUFBYSxHQUFHLE1BQU0sT0FBTyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2xELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzNDLFlBQVksQ0FDVixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssV0FBVztvQkFDdEQsQ0FBQyxDQUFDLE9BQU8sSUFBSSxRQUFRLElBQUksUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQ2pFLFNBQVMsQ0FDVixDQUFDO2dCQUNGLFlBQVksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7Z0JBQ3RGLE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDNUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDOUUsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzNELFlBQVksQ0FDVixzQkFBc0IsQ0FBQyxZQUFZLEtBQUssbUJBQW1CLENBQUMsWUFBWSxFQUN4RSxTQUFTLENBQ1YsQ0FBQztnQkFDRixNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzlDLFNBQVMsR0FBRyxTQUFTLENBQUM7Z0JBQ3RCLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNwQyxDQUFDO1lBQ0QsSUFBSSxDQUFDO2dCQUNILE1BQU0scUJBQXFCLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7Z0JBQ3BFLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDeEMsWUFBWSxDQUNWLEtBQUssQ0FBQyxLQUFLLENBQUM7b0JBQ1YsQ0FBQyxNQUFNLENBQUMsU0FBUyxLQUFLLFdBQVc7d0JBQy9CLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsYUFBYSxLQUFLLFVBQVU7d0JBQ3BFLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxLQUFLLE1BQU0sQ0FBQyxTQUFTOzRCQUNwQyxLQUFLLENBQUMsYUFBYSxLQUFLLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFDbkQsU0FBUyxDQUNWLENBQUM7Z0JBQ0YsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7Z0JBQzdELFlBQVksQ0FDVixDQUFDLHFCQUFxQixFQUFFLGFBQWEsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQ3hELENBQUMsUUFBUSxDQUFDLFdBQVcsSUFBSSxRQUFRLENBQUMsV0FBVyxLQUFLLEVBQUU7b0JBQ3BELFFBQVEsQ0FBQyxZQUFZO3dCQUNuQixDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2pFLEVBQ0QsYUFBYSxDQUNkLENBQUM7Z0JBQ0YsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3ZDLFlBQVksQ0FBQyxTQUFTLEVBQUUsTUFBTSxLQUFLLFVBQVUsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7Z0JBQ2pFLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQy9FLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsTUFBTSxJQUFJLG9CQUFvQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ2xELENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksS0FBSyxZQUFZLG9CQUFvQjtnQkFBRSxNQUFNLEtBQUssQ0FBQztZQUN2RCxNQUFNLElBQUksb0JBQW9CLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDakQsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDO2dCQUNILElBQUksU0FBUyxJQUFJLGFBQWEsRUFBRSxDQUFDO29CQUMvQixNQUFNLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO29CQUNoRCxZQUFZLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQztvQkFDNUQsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDckMsQ0FBQztZQUNILENBQUM7b0JBQVMsQ0FBQztnQkFDVCxJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQztZQUNwQixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQXdCO1FBQzFDLFlBQVksQ0FDVixLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO1lBQzVCLEtBQUssQ0FBQyxTQUFTLEtBQUssUUFBUTtnQkFDMUIsQ0FBQyxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsVUFBVSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUM7WUFDMUUsS0FBSyxDQUFDLFNBQVMsS0FBSyxXQUFXLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxFQUFFLENBQUMsRUFDaEUsYUFBYSxDQUNkLENBQUM7UUFDRixNQUFNLGFBQWEsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM3RCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxLQUFLLFFBQVE7WUFDdkMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQ2xCLEtBQUssQ0FBQyxhQUFhLEtBQUssZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxxQkFBcUIsRUFDeEYsSUFBSSxDQUFDLElBQUksQ0FDVixDQUFDO1lBQ0YsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGFBQWEsS0FBSyxnQkFBZ0I7Z0JBQ3pDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBaUIsRUFBRSxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDbEcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWdCLEVBQUUsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZHLFlBQVksQ0FDVixDQUFDLGFBQWEsQ0FBQyxXQUFXLElBQUksYUFBYSxDQUFDLFdBQVcsS0FBSyxFQUFFO1lBQzVELENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztnQkFDWixDQUFDLENBQUMsYUFBYSxDQUFDLFlBQVksS0FBSyxJQUFJLENBQUMsSUFBSTtvQkFDeEMsQ0FBQyxXQUFXLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQztnQkFDbEUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxZQUFZLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsRUFDeEYsYUFBYSxDQUNkLENBQUM7UUFDRixPQUFPLGFBQWEsQ0FBQztJQUN2QixDQUFDO0lBRU8sS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFlO1FBQ3ZDLFlBQVksQ0FBQyxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsS0FBSyxJQUFJLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzdGLElBQUksU0FBUyxHQUFHLEdBQUcsQ0FBQztRQUNwQixLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzdELFNBQVMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDL0MsSUFBSSxJQUFtQixDQUFDO1lBQ3hCLElBQUksQ0FBQztnQkFDSCxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMzQyxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixJQUFLLEtBQStCLENBQUMsSUFBSSxLQUFLLFFBQVE7b0JBQUUsTUFBTSxLQUFLLENBQUM7Z0JBQ3BFLElBQUksQ0FBQyxNQUFNO29CQUFFLE9BQU8sS0FBSyxDQUFDO2dCQUMxQixNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNuRCxNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUNsQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFDL0IsT0FBTyxDQUFDLFdBQVcsQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxXQUFXO29CQUM1RCxPQUFPLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FDakMsQ0FBQztnQkFDRixJQUFJLENBQUM7b0JBQ0gsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ3RCLENBQUM7d0JBQVMsQ0FBQztvQkFDVCxNQUFNLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDdkIsQ0FBQztnQkFDRCxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMzQyxDQUFDO1lBQ0QsWUFBWSxDQUNWLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7Z0JBQzlFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxTQUFTLEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQztvQkFDaEUsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLE1BQU0sQ0FBQyxFQUN0QyxhQUFhLENBQ2QsQ0FBQztRQUNKLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQVk7UUFDN0IsSUFBSSxJQUFpRCxDQUFDO1FBQ3RELElBQUksQ0FBQztZQUNILElBQUksR0FBRyxNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUMxQixJQUFJLEVBQ0osT0FBTyxDQUFDLFdBQVcsQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxVQUFVO2dCQUMzRCxPQUFPLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FDakMsQ0FBQztRQUNKLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSyxLQUErQixDQUFDLElBQUksS0FBSyxRQUFRO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBQ3BFLE1BQU0sSUFBSSxvQkFBb0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNoRCxDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0IsWUFBWSxDQUNWLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxDQUFDO2dCQUN4RCxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksS0FBSyxFQUN0RCxhQUFhLENBQ2QsQ0FBQztZQUNGLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbEMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO1lBQ2IsU0FBUyxDQUFDO2dCQUNSLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLEdBQUcsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUN2RSxJQUFJLE1BQU0sQ0FBQyxTQUFTLEtBQUssQ0FBQztvQkFBRSxNQUFNO2dCQUNsQyxJQUFJLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQztnQkFDekIsWUFBWSxDQUFDLElBQUksSUFBSSxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDN0MsQ0FBQztZQUNELE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RFLFlBQVksQ0FDVixRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSTtnQkFDckUsSUFBSSxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssS0FBSyxDQUFDLE9BQU87Z0JBQzFELElBQUksQ0FBQyxPQUFPLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFDaEMsU0FBUyxDQUNWLENBQUM7WUFDRixPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDO1FBQ2xELENBQUM7Z0JBQVMsQ0FBQztZQUNULE1BQU0sSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFZLEVBQUUsS0FBaUI7UUFDbEQsTUFBTSxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksQ0FDaEMsSUFBSSxFQUNKLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsTUFBTTtZQUN0RCxPQUFPLENBQUMsV0FBVyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFDL0QsS0FBSyxDQUNOLENBQUM7UUFDRixJQUFJLE9BQWtDLENBQUM7UUFDdkMsSUFBSSxDQUFDO1lBQ0gsSUFBSSxDQUFDO2dCQUNILE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDNUIsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN4QixNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzVCLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3BCLENBQUM7b0JBQVMsQ0FBQztnQkFDVCxNQUFNLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNyQixDQUFDO1FBQ0gsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLFlBQVksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQztnQkFDN0UsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNoQyxDQUFDO1lBQ0QsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjLENBQUMsUUFBdUI7UUFDbEQsTUFBTSxTQUFTLEdBQUcsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksQ0FDckMsSUFBSSxDQUFDLFNBQVMsRUFDZCxPQUFPLENBQUMsV0FBVyxDQUFDLFFBQVE7WUFDMUIsT0FBTyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQ25FLENBQUM7UUFDRixJQUFJLENBQUM7WUFDSCxZQUFZLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQ3hFLE1BQU0sU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3pCLENBQUM7Z0JBQVMsQ0FBQztZQUNULE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
|
|
@@ -4,8 +4,9 @@ import * as fs from 'node:fs/promises';
|
|
|
4
4
|
import { constants as fsConstants } from 'node:fs';
|
|
5
5
|
import * as crypto from 'node:crypto';
|
|
6
6
|
import * as util from 'node:util';
|
|
7
|
+
import * as os from 'node:os';
|
|
7
8
|
export type { Stats } from 'node:fs';
|
|
8
|
-
export { path, childProcess, fs, fsConstants, crypto, util };
|
|
9
|
+
export { path, childProcess, fs, fsConstants, crypto, util, os };
|
|
9
10
|
import * as lik from '@push.rocks/lik';
|
|
10
11
|
import * as smartfm from '@push.rocks/smartfm';
|
|
11
12
|
import * as smartfs from '@push.rocks/smartfs';
|
|
@@ -5,7 +5,8 @@ import * as fs from 'node:fs/promises';
|
|
|
5
5
|
import { constants as fsConstants } from 'node:fs';
|
|
6
6
|
import * as crypto from 'node:crypto';
|
|
7
7
|
import * as util from 'node:util';
|
|
8
|
-
|
|
8
|
+
import * as os from 'node:os';
|
|
9
|
+
export { path, childProcess, fs, fsConstants, crypto, util, os };
|
|
9
10
|
// @pushrocks scope
|
|
10
11
|
import * as lik from '@push.rocks/lik';
|
|
11
12
|
import * as smartfm from '@push.rocks/smartfm';
|
|
@@ -17,4 +18,4 @@ import * as smartshell from '@push.rocks/smartshell';
|
|
|
17
18
|
import * as smartsystem from '@push.rocks/smartsystem';
|
|
18
19
|
export { lik, smartfm, smartfs, smartlog, smartlogDestinationLocal, smartpath, smartshell, smartsystem, };
|
|
19
20
|
// third party
|
|
20
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYWVtb24ucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0ZGFlbW9uLnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxZQUFZLE1BQU0sb0JBQW9CLENBQUM7QUFDbkQsT0FBTyxLQUFLLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN2QyxPQUFPLEVBQUUsU0FBUyxJQUFJLFdBQVcsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNuRCxPQUFPLEtBQUssTUFBTSxNQUFNLGFBQWEsQ0FBQztBQUN0QyxPQUFPLEtBQUssSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUc5QixPQUFPLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFFakUsbUJBQW1CO0FBQ25CLE9BQU8sS0FBSyxHQUFHLE1BQU0saUJBQWlCLENBQUM7QUFDdkMsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEtBQUssT0FBTyxNQUFNLHFCQUFxQixDQUFDO0FBQy9DLE9BQU8sS0FBSyxRQUFRLE1BQU0sc0JBQXNCLENBQUM7QUFDakQsT0FBTyxLQUFLLHdCQUF3QixNQUFNLHdDQUF3QyxDQUFDO0FBQ25GLE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxLQUFLLFVBQVUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBRXZELE9BQU8sRUFDTCxHQUFHLEVBQ0gsT0FBTyxFQUNQLE9BQU8sRUFDUCxRQUFRLEVBQ1Isd0JBQXdCLEVBQ3hCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsV0FBVyxHQUNaLENBQUM7QUFFRixjQUFjIn0=
|
|
@@ -3,7 +3,7 @@ export interface ISystemdServiceStartup {
|
|
|
3
3
|
remainAfterExit: boolean;
|
|
4
4
|
timeoutStartSeconds: number;
|
|
5
5
|
}
|
|
6
|
-
/** Complete literal relations. After=local-fs.target
|
|
6
|
+
/** Complete literal relations. System services always retain After=local-fs.target. */
|
|
7
7
|
export interface ISystemdServiceDependencies {
|
|
8
8
|
defaultDependencies: boolean;
|
|
9
9
|
after: readonly string[];
|
|
@@ -22,7 +22,7 @@ export declare const renderServiceRelations: (options: {
|
|
|
22
22
|
startup?: ISystemdServiceStartup;
|
|
23
23
|
dependencies?: ISystemdServiceDependencies;
|
|
24
24
|
install?: ISystemdServiceInstallTargets;
|
|
25
|
-
}, unitName: string, restart: string, fail: () => never) => {
|
|
25
|
+
}, unitName: string, restart: string, scope: "system" | "user", fail: () => never) => {
|
|
26
26
|
unit: string[];
|
|
27
27
|
service: string[];
|
|
28
28
|
install: string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as plugins from './smartdaemon.plugins.js';
|
|
2
2
|
/** Internal validated renderer; no systemd/process/filesystem effects. */
|
|
3
|
-
export const renderServiceRelations = (options, unitName, restart, fail) => {
|
|
3
|
+
export const renderServiceRelations = (options, unitName, restart, scope, fail) => {
|
|
4
4
|
const requireValue = (value) => { if (!value)
|
|
5
5
|
fail(); };
|
|
6
6
|
const record = (value, keys) => {
|
|
@@ -27,7 +27,11 @@ export const renderServiceRelations = (options, unitName, restart, fail) => {
|
|
|
27
27
|
return result.sort();
|
|
28
28
|
};
|
|
29
29
|
const line = (key, value) => value.length ? [`${key}=${value.join(' ')}`] : [];
|
|
30
|
-
const result = {
|
|
30
|
+
const result = {
|
|
31
|
+
unit: scope === 'system' ? ['After=local-fs.target'] : [],
|
|
32
|
+
service: ['Type=exec'],
|
|
33
|
+
install: [scope === 'system' ? 'WantedBy=multi-user.target' : 'WantedBy=default.target'],
|
|
34
|
+
};
|
|
31
35
|
if (options.startup !== undefined) {
|
|
32
36
|
const value = options.startup;
|
|
33
37
|
record(value, ['type', 'remainAfterExit', 'timeoutStartSeconds']);
|
|
@@ -39,7 +43,7 @@ export const renderServiceRelations = (options, unitName, restart, fail) => {
|
|
|
39
43
|
const value = options.dependencies;
|
|
40
44
|
record(value, ['defaultDependencies', 'after', 'before', 'requires', 'wants', 'conflicts']);
|
|
41
45
|
requireValue(typeof value.defaultDependencies === 'boolean');
|
|
42
|
-
const after = [...new Set(['local-fs.target', ...units(value.after)])].sort();
|
|
46
|
+
const after = [...new Set([...(scope === 'system' ? ['local-fs.target'] : []), ...units(value.after)])].sort();
|
|
43
47
|
const before = units(value.before), requires = units(value.requires), wants = units(value.wants), conflicts = units(value.conflicts);
|
|
44
48
|
requireValue(before.every(item => !after.includes(item)) && conflicts.every(item => !requires.includes(item) && !wants.includes(item)));
|
|
45
49
|
result.unit = [`DefaultDependencies=${value.defaultDependencies ? 'yes' : 'no'}`, ...line('After', after),
|
|
@@ -54,4 +58,4 @@ export const renderServiceRelations = (options, unitName, restart, fail) => {
|
|
|
54
58
|
}
|
|
55
59
|
return result;
|
|
56
60
|
};
|
|
57
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3lzdGVtZC5kZWZpbml0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc3lzdGVtZC5kZWZpbml0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMEJBQTBCLENBQUM7QUF3QnBELDBFQUEwRTtBQUMxRSxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLE9BSXRDLEVBQUUsUUFBZ0IsRUFBRSxPQUFlLEVBQUUsS0FBd0IsRUFBRSxJQUFpQixFQUUvRSxFQUFFO0lBQ0YsTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFjLEVBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLO1FBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkUsTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFjLEVBQUUsSUFBdUIsRUFBUSxFQUFFO1FBQy9ELFlBQVksQ0FBQyxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7ZUFDekYsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsS0FBSyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDeEQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFlLENBQUMsQ0FBQztRQUNoRCxZQUFZLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEdBQUcsS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUM7ZUFDMUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRSxVQUFVLElBQUksT0FBTyxJQUFJLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzVILENBQUMsQ0FBQztJQUNGLE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBd0IsRUFBWSxFQUFFO1FBQ25ELFlBQVksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztlQUNsRSxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxFQUFFO2VBQ3RFLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxLQUFLLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDekQsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO1FBQzVCLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDbEQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUN6RSxZQUFZLENBQUMsVUFBVSxFQUFFLFVBQVUsSUFBSSxPQUFPLElBQUksVUFBVSxDQUFDLENBQUM7WUFDOUQsTUFBTSxJQUFJLEdBQUcsVUFBVyxDQUFDLEtBQUssQ0FBQztZQUMvQixZQUFZLENBQUMsT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxHQUFHO21CQUMzRSxnSEFBZ0gsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNsSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BCLENBQUM7UUFDRCxZQUFZLENBQUMsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNyRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN2QixDQUFDLENBQUM7SUFDRixNQUFNLElBQUksR0FBRyxDQUFDLEdBQVcsRUFBRSxLQUF3QixFQUFZLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDcEgsTUFBTSxNQUFNLEdBQUc7UUFDYixJQUFJLEVBQUUsS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFjO1FBQ3JFLE9BQU8sRUFBRSxDQUFDLFdBQVcsQ0FBQztRQUN0QixPQUFPLEVBQUUsQ0FBQyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDLENBQUMseUJBQXlCLENBQUM7S0FDekYsQ0FBQztJQUNGLElBQUksT0FBTyxDQUFDLE9BQU8sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNsQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDO1FBQzlCLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLEVBQUUscUJBQXFCLENBQUMsQ0FBQyxDQUFDO1FBQ2xFLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxPQUFPLEtBQUssQ0FBQyxlQUFlLEtBQUssU0FBUyxJQUFJLE9BQU8sS0FBSyxRQUFRO2VBQ3RHLE1BQU0sQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLElBQUksS0FBSyxDQUFDLG1CQUFtQixJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsbUJBQW1CLElBQUksR0FBRyxDQUFDLENBQUM7UUFDNUgsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUFDLGNBQWMsRUFBRSxtQkFBbUIsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxtQkFBbUIsS0FBSyxDQUFDLG1CQUFtQixHQUFHLENBQUMsQ0FBQztJQUNoSixDQUFDO0lBQ0QsSUFBSSxPQUFPLENBQUMsWUFBWSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7UUFDbkMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLHFCQUFxQixFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQzVGLFlBQVksQ0FBQyxPQUFPLEtBQUssQ0FBQyxtQkFBbUIsS0FBSyxTQUFTLENBQUMsQ0FBQztRQUM3RCxNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDL0csTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxRQUFRLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsRUFBRSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxTQUFTLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNySSxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4SSxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsdUJBQXVCLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDO1lBQ3ZHLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3hILENBQUM7SUFDRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDbEMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUM5QixNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDMUMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsRUFBRSxRQUFRLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN6RSxZQUFZLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRyxNQUFNLENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQ2xGLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartdaemon",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Start scripts as long running daemons and manage them.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://code.foss.global/push.rocks/smartdaemon",
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@git.zone/tsbuild": "^
|
|
30
|
-
"@git.zone/tsrun": "^
|
|
31
|
-
"@git.zone/tstest": "^6.
|
|
32
|
-
"@types/node": "^26.
|
|
29
|
+
"@git.zone/tsbuild": "^5.0.0",
|
|
30
|
+
"@git.zone/tsrun": "^3.0.0",
|
|
31
|
+
"@git.zone/tstest": "^6.2.1",
|
|
32
|
+
"@types/node": "^26.6.1"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@push.rocks/lik": "^6.4.1",
|
package/readme.md
CHANGED
|
@@ -164,6 +164,10 @@ const unit = new SystemdUnit({ unitName: 'smartdaemon_my-api-server.service' });
|
|
|
164
164
|
const state = await unit.inspect();
|
|
165
165
|
console.log(state.loadState, state.activeState, state.unitFileState);
|
|
166
166
|
|
|
167
|
+
// Address the calling user's manager when running as that user.
|
|
168
|
+
const userUnit = new SystemdUnit({ unitName: 'authswitch.service', scope: 'user' });
|
|
169
|
+
const userState = await userUnit.inspect();
|
|
170
|
+
|
|
167
171
|
// Application code decides whether stopping or restarting is appropriate.
|
|
168
172
|
// await unit.stop();
|
|
169
173
|
// await unit.start();
|
|
@@ -185,6 +189,17 @@ Calls use an absolute `systemctlPath` (default `/usr/bin/systemctl`), a clean
|
|
|
185
189
|
environment, no shell or password prompt, and bounded output. Trusted owning code
|
|
186
190
|
can choose another absolute executable path and `commandTimeoutMs` (default
|
|
187
191
|
120000, maximum 600000). This timeout bounds the client process only.
|
|
192
|
+
The default `scope: 'system'` retains system-manager behavior. `scope: 'user'`
|
|
193
|
+
uses `systemctl --user` as the calling user. Every `SystemdUnit` operation contacts
|
|
194
|
+
the user manager, so each requires a real, owned, private `XDG_RUNTIME_DIR` (or an
|
|
195
|
+
explicit `runtimeDirectory`) and passes that directory with the user's home and
|
|
196
|
+
valid XDG config/data roots to the command. The directory is checked again before
|
|
197
|
+
each call; a missing, replaced, linked or group-accessible runtime directory fails
|
|
198
|
+
with `invalid_options` before contacting systemd. Construction itself does not
|
|
199
|
+
require one, so a unit can be constructed without a login session (cron, a plain
|
|
200
|
+
ssh command); an empty `XDG_RUNTIME_DIR` counts as unset. A supplied directory, from
|
|
201
|
+
the option or a non-empty `XDG_RUNTIME_DIR`, that is not an absolute, normalized path
|
|
202
|
+
without a trailing slash is still rejected at construction.
|
|
188
203
|
|
|
189
204
|
`inspectConfiguration()` reports the selected `fragmentPath`, opaque `dropInPaths`
|
|
190
205
|
list and `needsReload` flag. `reloadConfiguration()` explicitly reloads the manager's
|
|
@@ -211,7 +226,9 @@ drop-ins and `needsReload === false` before permitting dependent activation.
|
|
|
211
226
|
### Installing a direct systemd service definition
|
|
212
227
|
|
|
213
228
|
`SystemdServiceDefinition` encodes a literal executable and argument list, with
|
|
214
|
-
explicit
|
|
229
|
+
explicit restart policy, kill mode and stop timeout. System-scope definitions require
|
|
230
|
+
`user` and `group`; user-scope definitions reject both directives because the user
|
|
231
|
+
manager already runs under the calling identity. It defaults to `Type=exec`,
|
|
215
232
|
journal output and null stdin. It introduces no shell; percent specifiers and
|
|
216
233
|
argument environment expansion are escaped. Paths must be absolute and normalized;
|
|
217
234
|
control characters are rejected. Descriptions and working directories cannot have
|
|
@@ -240,6 +257,45 @@ const installed = await file.install(definition, previous?.sha256 ?? null);
|
|
|
240
257
|
console.log(installed.changed, installed.masked, installed.record.sha256);
|
|
241
258
|
```
|
|
242
259
|
|
|
260
|
+
For a user service, give the definition and installer the same scope:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const userDefinition = new SystemdServiceDefinition({
|
|
264
|
+
scope: 'user',
|
|
265
|
+
unitName: 'authswitch.service',
|
|
266
|
+
description: 'Account authority',
|
|
267
|
+
executable: '/opt/authswitch/bin/authswitch',
|
|
268
|
+
args: ['daemon'],
|
|
269
|
+
workingDirectory: '/opt/authswitch',
|
|
270
|
+
restart: 'on-failure',
|
|
271
|
+
killMode: 'mixed',
|
|
272
|
+
timeoutStopSeconds: 60,
|
|
273
|
+
});
|
|
274
|
+
const userFile = new SystemdUnitFile({ scope: 'user', unitName: userDefinition.unitName });
|
|
275
|
+
const previousUserFile = await userFile.inspect();
|
|
276
|
+
await userFile.install(userDefinition, previousUserFile?.sha256 ?? null);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
User definitions default to `WantedBy=default.target` and have no system-only
|
|
280
|
+
`After=local-fs.target` edge. User unit files default to
|
|
281
|
+
`$XDG_DATA_HOME/systemd/user` (or `~/.local/share/systemd/user`), below the user's
|
|
282
|
+
config directory in the unit load path. Installation and enablement use the
|
|
283
|
+
current user manager and do not escalate privileges. The installer rejects unsafe
|
|
284
|
+
ownership or group-writable path components; prepare those directories explicitly
|
|
285
|
+
before installation. It never changes the permissions of existing directories.
|
|
286
|
+
|
|
287
|
+
A user-scope `SystemdUnitFile` needs the user manager's runtime directory only for
|
|
288
|
+
`install()`, which admits, reloads and verifies through the manager. Without one,
|
|
289
|
+
`install()` rejects with `invalid_options` before touching any directory or running
|
|
290
|
+
`systemctl`. Construction and `inspect()` read only the unit directory and work
|
|
291
|
+
without it, so an owner can ask whether its definition is installed from a context
|
|
292
|
+
without a login session:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// Resolves to null when the file is absent, or { path, sha256 } for a protected definition.
|
|
296
|
+
const installed = await new SystemdUnitFile({ scope: 'user', unitName: 'authswitch.service' }).inspect();
|
|
297
|
+
```
|
|
298
|
+
|
|
243
299
|
For a boot prerequisite that must finish before dependent services start, supply
|
|
244
300
|
`startup: { type: 'oneshot', remainAfterExit: true, timeoutStartSeconds: 120 }`.
|
|
245
301
|
Systemd waits for successful process exit; `RemainAfterExit` keeps the completed
|
|
@@ -260,7 +316,7 @@ dependencies: {
|
|
|
260
316
|
install: { wantedBy: [], requiredBy: ['network-pre.target', 'systemd-networkd.service'] },
|
|
261
317
|
```
|
|
262
318
|
|
|
263
|
-
`After=local-fs.target
|
|
319
|
+
System definitions always retain `After=local-fs.target`. Disable default dependencies only for
|
|
264
320
|
an intentionally early boot or late shutdown service. Every list is bounded to
|
|
265
321
|
32 distinct literal unit names, sorted deterministically; templates, specifiers,
|
|
266
322
|
self references and contradictory direct relationships are rejected. These local
|
|
@@ -305,17 +361,21 @@ read-only ISO. The API fixture checks enablement without implicit start, oneshot
|
|
|
305
361
|
readiness, unchanged definition/configuration, detection of a missing provider
|
|
306
362
|
link despite enabled state, exact enable retry and preservation of a mask.
|
|
307
363
|
|
|
308
|
-
Installation requires Linux,
|
|
364
|
+
Installation requires Linux, the relevant manager's user identity and a quiescent
|
|
365
|
+
exact unit with no process,
|
|
309
366
|
cgroup or job. It rejects effective drop-ins and shadowing fragments. Definitions
|
|
310
|
-
default to `/usr/local/lib/systemd/system
|
|
311
|
-
|
|
367
|
+
default to `/usr/local/lib/systemd/system` for system scope and the user's data
|
|
368
|
+
unit directory for user scope, below administrator or user configuration in the
|
|
369
|
+
load path, so existing persistent/runtime masks remain intact. Existing
|
|
312
370
|
enablement is preserved; an absent unit becomes disabled. It never enables,
|
|
313
371
|
unmasks, starts or stops a service, or invokes sudo.
|
|
314
372
|
|
|
315
|
-
Masked units may report `/dev/null` or their exact administrator mask path:
|
|
373
|
+
Masked system units may report `/dev/null` or their exact administrator mask path:
|
|
316
374
|
`/etc/systemd/system/<unit>` for a persistent mask, `/run/systemd/system/<unit>`
|
|
317
375
|
for a runtime mask. Installation preserves that exact manager-selected fragment
|
|
318
376
|
through the write and reload, and never replaces the masking fragment itself.
|
|
377
|
+
For user scope, the exact user config or runtime mask path and the global user-unit
|
|
378
|
+
mask paths are also recognized.
|
|
319
379
|
Pending manager reloads are rejected before writing; inspect and explicitly
|
|
320
380
|
reload an existing changed configuration before retrying installation.
|
|
321
381
|
|
|
@@ -329,7 +389,10 @@ the manager and checks its selected fragment and final bytes. A reload failure
|
|
|
329
389
|
leaves the new file and retained previous definition in place; recovery requires
|
|
330
390
|
inspection, never an automatic rollback. Filesystem and definition errors use
|
|
331
391
|
`SystemdUnitFileError` with a local code. Trusted qualification code can set
|
|
332
|
-
`unitDirectory`, `expectedUid` and the inherited `SystemdUnit` command options
|
|
392
|
+
`unitDirectory`, `expectedUid` and the inherited `SystemdUnit` command options;
|
|
393
|
+
user scope requires `expectedUid` to match the caller's actual uid. The manager's
|
|
394
|
+
selected fragment must match the installed file after reload, so an unrecognized
|
|
395
|
+
custom user unit path fails closed.
|
|
333
396
|
|
|
334
397
|
With `killMode: 'mixed'`, the main process owns graceful child shutdown and must
|
|
335
398
|
remain alive until its children have joined. Systemd sends SIGTERM to the main
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,14 +3,12 @@ import { renderServiceRelations, type ISystemdServiceStartup, type ISystemdServi
|
|
|
3
3
|
type ISystemdServiceInstallTargets } from './systemd.definition.js';
|
|
4
4
|
export type { ISystemdServiceStartup, ISystemdServiceDependencies, ISystemdServiceInstallTargets } from './systemd.definition.js';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
interface ISystemdServiceDefinitionBaseOptions {
|
|
7
7
|
unitName: string;
|
|
8
8
|
description: string;
|
|
9
9
|
executable: string;
|
|
10
10
|
args: readonly string[];
|
|
11
11
|
workingDirectory: string;
|
|
12
|
-
user: string;
|
|
13
|
-
group: string;
|
|
14
12
|
restart: 'no' | 'on-failure' | 'always';
|
|
15
13
|
killMode: 'mixed' | 'control-group';
|
|
16
14
|
timeoutStopSeconds: number;
|
|
@@ -19,6 +17,11 @@ export interface ISystemdServiceDefinitionOptions {
|
|
|
19
17
|
install?: ISystemdServiceInstallTargets;
|
|
20
18
|
}
|
|
21
19
|
|
|
20
|
+
export type ISystemdServiceDefinitionOptions = ISystemdServiceDefinitionBaseOptions & (
|
|
21
|
+
{ scope?: 'system'; user: string; group: string } |
|
|
22
|
+
{ scope: 'user'; user?: never; group?: never }
|
|
23
|
+
);
|
|
24
|
+
|
|
22
25
|
export class SystemdServiceDefinitionError extends Error {
|
|
23
26
|
constructor() {
|
|
24
27
|
super('Invalid direct systemd service definition.');
|
|
@@ -29,6 +32,7 @@ export class SystemdServiceDefinitionError extends Error {
|
|
|
29
32
|
/** Literal direct-execution definition; never introduces a shell or environment expansion. */
|
|
30
33
|
export class SystemdServiceDefinition {
|
|
31
34
|
public readonly unitName: string;
|
|
35
|
+
public readonly scope: 'system' | 'user';
|
|
32
36
|
public readonly content: string;
|
|
33
37
|
public readonly sha256: string;
|
|
34
38
|
|
|
@@ -36,6 +40,16 @@ export class SystemdServiceDefinition {
|
|
|
36
40
|
const requireValue = (value: unknown): void => {
|
|
37
41
|
if (!value) throw new SystemdServiceDefinitionError();
|
|
38
42
|
};
|
|
43
|
+
requireValue(options && !plugins.util.types.isProxy(options) &&
|
|
44
|
+
Object.getPrototypeOf(options) === Object.prototype);
|
|
45
|
+
const scopeDescriptor = Object.getOwnPropertyDescriptor(options, 'scope');
|
|
46
|
+
requireValue(scopeDescriptor === undefined ||
|
|
47
|
+
scopeDescriptor.enumerable && 'value' in scopeDescriptor);
|
|
48
|
+
const scopeValue: unknown = scopeDescriptor?.value ?? 'system';
|
|
49
|
+
if (scopeValue !== 'system' && scopeValue !== 'user') {
|
|
50
|
+
throw new SystemdServiceDefinitionError();
|
|
51
|
+
}
|
|
52
|
+
const scope = scopeValue;
|
|
39
53
|
const text = (value: unknown, maximum = 4096): value is string =>
|
|
40
54
|
typeof value === 'string' && value.length <= maximum && !/[\x00-\x1f\x7f]/.test(value) &&
|
|
41
55
|
!/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u.test(value);
|
|
@@ -48,15 +62,13 @@ export class SystemdServiceDefinition {
|
|
|
48
62
|
'executable',
|
|
49
63
|
'args',
|
|
50
64
|
'workingDirectory',
|
|
51
|
-
'user',
|
|
52
|
-
'group',
|
|
53
65
|
'restart',
|
|
54
66
|
'killMode',
|
|
55
67
|
'timeoutStopSeconds',
|
|
68
|
+
...(scope === 'system' ? ['user', 'group'] : []),
|
|
56
69
|
];
|
|
57
70
|
requireValue(
|
|
58
|
-
|
|
59
|
-
Reflect.ownKeys(options).every(key => typeof key === 'string' && [...keys, 'startup', 'dependencies', 'install'].includes(key)
|
|
71
|
+
Reflect.ownKeys(options).every(key => typeof key === 'string' && [...keys, 'scope', 'startup', 'dependencies', 'install'].includes(key)
|
|
60
72
|
&& Object.getOwnPropertyDescriptor(options, key)?.enumerable && 'value' in Object.getOwnPropertyDescriptor(options, key)!) && keys.every((key) => {
|
|
61
73
|
const descriptor = Object.getOwnPropertyDescriptor(options, key);
|
|
62
74
|
return descriptor && 'value' in descriptor;
|
|
@@ -87,11 +99,13 @@ export class SystemdServiceDefinition {
|
|
|
87
99
|
)
|
|
88
100
|
.every((descriptor) => descriptor && 'value' in descriptor && text(descriptor.value)),
|
|
89
101
|
);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
102
|
+
if (scope === 'system') {
|
|
103
|
+
requireValue(
|
|
104
|
+
[options.user, options.group].every((value) =>
|
|
105
|
+
typeof value === 'string' && /^[a-zA-Z_][a-zA-Z0-9_-]{0,63}$/.test(value)
|
|
106
|
+
),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
95
109
|
requireValue(
|
|
96
110
|
['no', 'on-failure', 'always'].includes(options.restart) &&
|
|
97
111
|
['mixed', 'control-group'].includes(options.killMode) &&
|
|
@@ -104,8 +118,9 @@ export class SystemdServiceDefinition {
|
|
|
104
118
|
.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll('%', '%%')
|
|
105
119
|
.replaceAll('$', () => command ? '$$' : '$') +
|
|
106
120
|
'"';
|
|
107
|
-
const relations = renderServiceRelations(options, options.unitName, options.restart, () => { throw new SystemdServiceDefinitionError(); });
|
|
121
|
+
const relations = renderServiceRelations(options, options.unitName, options.restart, scope, () => { throw new SystemdServiceDefinitionError(); });
|
|
108
122
|
this.unitName = options.unitName;
|
|
123
|
+
this.scope = scope;
|
|
109
124
|
this.content = [
|
|
110
125
|
'[Unit]',
|
|
111
126
|
`Description=${options.description.replaceAll('%', '%%')}`,
|
|
@@ -113,8 +128,7 @@ export class SystemdServiceDefinition {
|
|
|
113
128
|
'',
|
|
114
129
|
'[Service]',
|
|
115
130
|
...relations.service,
|
|
116
|
-
`User=${options.user}`,
|
|
117
|
-
`Group=${options.group}`,
|
|
131
|
+
...(scope === 'system' ? [`User=${options.user}`, `Group=${options.group}`] : []),
|
|
118
132
|
`ExecStart=${
|
|
119
133
|
[quote(options.executable), ...options.args.map((value) => quote(value, true))].join(' ')
|
|
120
134
|
}`,
|
|
@@ -2,6 +2,13 @@ import * as plugins from './smartdaemon.plugins.js';
|
|
|
2
2
|
|
|
3
3
|
export interface ISystemdUnitOptions {
|
|
4
4
|
unitName: string;
|
|
5
|
+
/** Defaults to the system manager. User scope addresses the calling user's manager only. */
|
|
6
|
+
scope?: 'system' | 'user';
|
|
7
|
+
/**
|
|
8
|
+
* User-manager socket directory. Defaults to a non-empty XDG_RUNTIME_DIR. May be absent at
|
|
9
|
+
* construction; every call that contacts the user manager then refuses with `invalid_options`.
|
|
10
|
+
*/
|
|
11
|
+
runtimeDirectory?: string;
|
|
5
12
|
/** Absolute executable path supplied by trusted owning code. */
|
|
6
13
|
systemctlPath?: string;
|
|
7
14
|
/** Bounds the systemctl client, not the server-side job. Defaults to 120 seconds. */
|
|
@@ -66,17 +73,44 @@ export class SystemdUnit {
|
|
|
66
73
|
private readonly unitName: string;
|
|
67
74
|
private readonly executable: string;
|
|
68
75
|
private readonly timeout: number;
|
|
76
|
+
private readonly scope: 'system' | 'user';
|
|
77
|
+
private readonly runtimeDirectory?: string;
|
|
78
|
+
private readonly homeDirectory?: string;
|
|
79
|
+
private readonly configDirectory?: string;
|
|
80
|
+
private readonly dataDirectory?: string;
|
|
69
81
|
|
|
70
82
|
constructor(optionsArg: ISystemdUnitOptions) {
|
|
71
83
|
this.unitName = optionsArg?.unitName;
|
|
72
84
|
this.executable = optionsArg?.systemctlPath ?? '/usr/bin/systemctl';
|
|
73
85
|
this.timeout = optionsArg?.commandTimeoutMs ?? 120000;
|
|
86
|
+
this.scope = optionsArg?.scope ?? 'system';
|
|
87
|
+
// An empty XDG_RUNTIME_DIR counts as unset, like the sibling XDG variables below. An explicit
|
|
88
|
+
// option is never reinterpreted, so an empty or relative option stays malformed.
|
|
89
|
+
this.runtimeDirectory = this.scope === 'user'
|
|
90
|
+
? optionsArg?.runtimeDirectory ?? (process.env.XDG_RUNTIME_DIR || undefined) : undefined;
|
|
91
|
+
this.homeDirectory = this.scope === 'user' ? plugins.os.userInfo().homedir : undefined;
|
|
92
|
+
this.configDirectory = this.scope === 'user' ? process.env.XDG_CONFIG_HOME || undefined : undefined;
|
|
93
|
+
this.dataDirectory = this.scope === 'user' ? process.env.XDG_DATA_HOME || undefined : undefined;
|
|
94
|
+
const safeDirectory = (value: unknown): value is string =>
|
|
95
|
+
typeof value === 'string' && value !== '/' && plugins.path.isAbsolute(value) &&
|
|
96
|
+
plugins.path.normalize(value) === value && !value.endsWith('/') &&
|
|
97
|
+
value.length <= 4000 && !/[\x00-\x1f\x7f]/.test(value);
|
|
98
|
+
// Only a supplied runtime directory is validated here. Its absence matters solely to calls that
|
|
99
|
+
// reach the user manager, and those refuse it in validateUserRuntime(). Admitting absence lets
|
|
100
|
+
// owners read protected unit files from contexts without a login session (cron, plain ssh).
|
|
74
101
|
if (
|
|
75
102
|
typeof this.unitName !== 'string' ||
|
|
76
103
|
!/^[a-zA-Z0-9][a-zA-Z0-9_.:@-]{0,230}\.service$/.test(this.unitName) ||
|
|
77
104
|
typeof this.executable !== 'string' || !plugins.path.isAbsolute(this.executable) ||
|
|
78
105
|
this.executable.includes('\0') || !Number.isSafeInteger(this.timeout) ||
|
|
79
|
-
this.timeout < 1 || this.timeout > 600000
|
|
106
|
+
this.timeout < 1 || this.timeout > 600000 ||
|
|
107
|
+
!['system', 'user'].includes(this.scope) ||
|
|
108
|
+
(this.scope === 'system' && optionsArg?.runtimeDirectory !== undefined) ||
|
|
109
|
+
(this.scope === 'user' &&
|
|
110
|
+
(this.runtimeDirectory !== undefined && !safeDirectory(this.runtimeDirectory) ||
|
|
111
|
+
!safeDirectory(this.homeDirectory) ||
|
|
112
|
+
this.configDirectory !== undefined && !safeDirectory(this.configDirectory) ||
|
|
113
|
+
this.dataDirectory !== undefined && !safeDirectory(this.dataDirectory)))
|
|
80
114
|
) throw new SystemdUnitError('invalid_options');
|
|
81
115
|
}
|
|
82
116
|
|
|
@@ -193,18 +227,43 @@ export class SystemdUnit {
|
|
|
193
227
|
return this.inspectConfiguration();
|
|
194
228
|
}
|
|
195
229
|
|
|
196
|
-
private
|
|
230
|
+
private async validateUserRuntime(): Promise<void> {
|
|
231
|
+
if (this.scope !== 'user') return;
|
|
232
|
+
// Runs before every systemctl invocation, so a missing directory refuses without side effects.
|
|
233
|
+
const runtimeDirectory = this.runtimeDirectory;
|
|
234
|
+
if (runtimeDirectory === undefined) throw new SystemdUnitError('invalid_options');
|
|
235
|
+
try {
|
|
236
|
+
const uid = process.getuid?.();
|
|
237
|
+
if (process.platform !== 'linux' || uid === undefined || process.geteuid?.() !== uid ||
|
|
238
|
+
await plugins.fs.realpath(runtimeDirectory) !== runtimeDirectory) {
|
|
239
|
+
throw new SystemdUnitError('invalid_options');
|
|
240
|
+
}
|
|
241
|
+
const info = await plugins.fs.lstat(runtimeDirectory);
|
|
242
|
+
if (!info.isDirectory() || info.isSymbolicLink() || info.uid !== uid ||
|
|
243
|
+
(info.mode & 0o077) !== 0) throw new SystemdUnitError('invalid_options');
|
|
244
|
+
} catch {
|
|
245
|
+
throw new SystemdUnitError('invalid_options');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private async command(argsArg: string[]): Promise<string> {
|
|
250
|
+
await this.validateUserRuntime();
|
|
197
251
|
return new Promise((resolve, reject) => {
|
|
198
252
|
plugins.childProcess.execFile(
|
|
199
253
|
this.executable,
|
|
200
|
-
['--system', '--no-ask-password', '--no-pager', ...argsArg],
|
|
254
|
+
[this.scope === 'user' ? '--user' : '--system', '--no-ask-password', '--no-pager', ...argsArg],
|
|
201
255
|
{
|
|
202
256
|
encoding: 'utf8',
|
|
203
257
|
timeout: this.timeout,
|
|
204
258
|
killSignal: 'SIGKILL',
|
|
205
259
|
maxBuffer: 16384,
|
|
206
260
|
windowsHide: true,
|
|
207
|
-
env:
|
|
261
|
+
env: this.scope === 'user'
|
|
262
|
+
? { PATH: '/usr/bin:/bin', LANG: 'C', LC_ALL: 'C',
|
|
263
|
+
HOME: this.homeDirectory!, XDG_RUNTIME_DIR: this.runtimeDirectory!,
|
|
264
|
+
...(this.configDirectory ? { XDG_CONFIG_HOME: this.configDirectory } : {}),
|
|
265
|
+
...(this.dataDirectory ? { XDG_DATA_HOME: this.dataDirectory } : {}) }
|
|
266
|
+
: { PATH: '/usr/bin:/bin', LANG: 'C', LC_ALL: 'C' },
|
|
208
267
|
},
|
|
209
268
|
(error, stdout) => {
|
|
210
269
|
// execFile settles after the client closes. A timed-out client's remote job may continue.
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
export interface ISystemdUnitFileOptions extends ISystemdUnitOptions {
|
|
11
11
|
/** Local vendor definitions can be installed without removing an administrator's mask. */
|
|
12
12
|
unitDirectory?: string;
|
|
13
|
-
/** Trusted owning-code qualification only. Defaults to root. */
|
|
13
|
+
/** Trusted owning-code qualification only. Defaults to root for system, current uid for user. */
|
|
14
14
|
expectedUid?: number;
|
|
15
15
|
}
|
|
16
16
|
export interface ISystemdUnitFileRecord {
|
|
@@ -56,6 +56,9 @@ export class SystemdUnitFile {
|
|
|
56
56
|
public readonly path: string;
|
|
57
57
|
private readonly directory: string;
|
|
58
58
|
private readonly uid: number;
|
|
59
|
+
private readonly scope: 'system' | 'user';
|
|
60
|
+
private readonly configDirectory?: string;
|
|
61
|
+
private readonly runtimeDirectory?: string;
|
|
59
62
|
private readonly unit: SystemdUnit;
|
|
60
63
|
private readonly name: string;
|
|
61
64
|
private busy = false;
|
|
@@ -63,20 +66,39 @@ export class SystemdUnitFile {
|
|
|
63
66
|
constructor(options: ISystemdUnitFileOptions) {
|
|
64
67
|
this.unit = new SystemdUnit(options);
|
|
65
68
|
this.name = options.unitName;
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
69
|
+
this.scope = options.scope ?? 'system';
|
|
70
|
+
const home = this.scope === 'user' ? plugins.os.userInfo().homedir : undefined;
|
|
71
|
+
const dataDirectory = this.scope === 'user'
|
|
72
|
+
? process.env.XDG_DATA_HOME || plugins.path.join(home!, '.local/share') : undefined;
|
|
73
|
+
this.configDirectory = this.scope === 'user'
|
|
74
|
+
? process.env.XDG_CONFIG_HOME || plugins.path.join(home!, '.config') : undefined;
|
|
75
|
+
// Resolved exactly as SystemdUnit resolves it, so both agree on presence.
|
|
76
|
+
this.runtimeDirectory = this.scope === 'user'
|
|
77
|
+
? options.runtimeDirectory ?? (process.env.XDG_RUNTIME_DIR || undefined) : undefined;
|
|
78
|
+
this.directory = options.unitDirectory ?? (this.scope === 'user'
|
|
79
|
+
? plugins.path.join(dataDirectory!, 'systemd/user') : '/usr/local/lib/systemd/system');
|
|
80
|
+
this.uid = options.expectedUid ?? (this.scope === 'user' ? process.getuid?.() ?? -1 : 0);
|
|
81
|
+
const validDirectory = (directory: unknown): directory is string =>
|
|
82
|
+
typeof directory === 'string' && directory !== '/' &&
|
|
83
|
+
plugins.path.isAbsolute(directory) && plugins.path.normalize(directory) === directory &&
|
|
84
|
+
!directory.endsWith('/') && !/[\x00-\x1f\x7f]/.test(directory) &&
|
|
85
|
+
directory.length <= 4000;
|
|
68
86
|
requireValue(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
87
|
+
validDirectory(this.directory) && Number.isSafeInteger(this.uid) && this.uid >= 0 &&
|
|
88
|
+
(this.scope === 'system' ||
|
|
89
|
+
this.uid === process.getuid?.() && validDirectory(this.configDirectory) &&
|
|
90
|
+
// inspect() reads only the unit directory, so an absent runtime directory is refused
|
|
91
|
+
// later, by install(); a supplied one must still be well formed.
|
|
92
|
+
(this.runtimeDirectory === undefined || validDirectory(this.runtimeDirectory))),
|
|
74
93
|
'invalid_options',
|
|
75
94
|
);
|
|
76
95
|
this.path = plugins.path.join(this.directory, this.name);
|
|
77
96
|
}
|
|
78
97
|
|
|
79
|
-
/**
|
|
98
|
+
/**
|
|
99
|
+
* Reads only the exact protected definition; no systemd or filesystem mutation.
|
|
100
|
+
* Needs no user-manager runtime directory.
|
|
101
|
+
*/
|
|
80
102
|
public async inspect(): Promise<ISystemdUnitFileRecord | null> {
|
|
81
103
|
if (!await this.directories(false)) return null;
|
|
82
104
|
const file = await this.read(this.path);
|
|
@@ -93,8 +115,13 @@ export class SystemdUnitFile {
|
|
|
93
115
|
): Promise<Readonly<{ changed: boolean; record: ISystemdUnitFileRecord; masked: boolean }>> {
|
|
94
116
|
requireValue(
|
|
95
117
|
definition instanceof SystemdServiceDefinition && definition.unitName === this.name &&
|
|
118
|
+
definition.scope === this.scope &&
|
|
96
119
|
(expectedSha256 === null ||
|
|
97
|
-
typeof expectedSha256 === 'string' && /^[a-f0-9]{64}$/.test(expectedSha256))
|
|
120
|
+
typeof expectedSha256 === 'string' && /^[a-f0-9]{64}$/.test(expectedSha256)) &&
|
|
121
|
+
// Installation admits, reloads and verifies through the user manager and recognizes its
|
|
122
|
+
// runtime mask path. Refusing here, before the busy latch and any directory or systemctl
|
|
123
|
+
// effect, keeps the local error code instead of a wrapped write_failed.
|
|
124
|
+
(this.scope === 'system' || this.runtimeDirectory !== undefined),
|
|
98
125
|
'invalid_options',
|
|
99
126
|
);
|
|
100
127
|
requireValue(!this.busy, 'busy');
|
|
@@ -196,15 +223,19 @@ export class SystemdUnitFile {
|
|
|
196
223
|
'unsafe_unit',
|
|
197
224
|
);
|
|
198
225
|
const configuration = await this.unit.inspectConfiguration();
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
226
|
+
const maskPaths = this.scope === 'system'
|
|
227
|
+
? [plugins.path.join(
|
|
228
|
+
state.unitFileState === 'masked-runtime' ? '/run/systemd/system' : '/etc/systemd/system',
|
|
229
|
+
this.name,
|
|
230
|
+
)]
|
|
231
|
+
: (state.unitFileState === 'masked-runtime'
|
|
232
|
+
? [this.runtimeDirectory!, '/run'].map(root => plugins.path.join(root, 'systemd/user', this.name))
|
|
233
|
+
: [this.configDirectory!, '/etc'].map(root => plugins.path.join(root, 'systemd/user', this.name)));
|
|
203
234
|
requireValue(
|
|
204
235
|
!configuration.needsReload && configuration.dropInPaths === '' &&
|
|
205
236
|
(masked(state)
|
|
206
237
|
? configuration.fragmentPath !== this.path &&
|
|
207
|
-
['/dev/null',
|
|
238
|
+
['/dev/null', ...maskPaths].includes(configuration.fragmentPath)
|
|
208
239
|
: configuration.fragmentPath === (state.loadState === 'not-found' ? '' : this.path)),
|
|
209
240
|
'unsafe_unit',
|
|
210
241
|
);
|
|
@@ -5,9 +5,10 @@ import * as fs from 'node:fs/promises';
|
|
|
5
5
|
import { constants as fsConstants } from 'node:fs';
|
|
6
6
|
import * as crypto from 'node:crypto';
|
|
7
7
|
import * as util from 'node:util';
|
|
8
|
+
import * as os from 'node:os';
|
|
8
9
|
export type { Stats } from 'node:fs';
|
|
9
10
|
|
|
10
|
-
export { path, childProcess, fs, fsConstants, crypto, util };
|
|
11
|
+
export { path, childProcess, fs, fsConstants, crypto, util, os };
|
|
11
12
|
|
|
12
13
|
// @pushrocks scope
|
|
13
14
|
import * as lik from '@push.rocks/lik';
|
package/ts/systemd.definition.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface ISystemdServiceStartup {
|
|
|
6
6
|
timeoutStartSeconds: number;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
/** Complete literal relations. After=local-fs.target
|
|
9
|
+
/** Complete literal relations. System services always retain After=local-fs.target. */
|
|
10
10
|
export interface ISystemdServiceDependencies {
|
|
11
11
|
defaultDependencies: boolean;
|
|
12
12
|
after: readonly string[];
|
|
@@ -27,7 +27,7 @@ export const renderServiceRelations = (options: {
|
|
|
27
27
|
startup?: ISystemdServiceStartup;
|
|
28
28
|
dependencies?: ISystemdServiceDependencies;
|
|
29
29
|
install?: ISystemdServiceInstallTargets;
|
|
30
|
-
}, unitName: string, restart: string, fail: () => never): {
|
|
30
|
+
}, unitName: string, restart: string, scope: 'system' | 'user', fail: () => never): {
|
|
31
31
|
unit: string[]; service: string[]; install: string[];
|
|
32
32
|
} => {
|
|
33
33
|
const requireValue = (value: unknown): void => { if (!value) fail(); };
|
|
@@ -55,7 +55,11 @@ export const renderServiceRelations = (options: {
|
|
|
55
55
|
return result.sort();
|
|
56
56
|
};
|
|
57
57
|
const line = (key: string, value: readonly string[]): string[] => value.length ? [`${key}=${value.join(' ')}`] : [];
|
|
58
|
-
const result = {
|
|
58
|
+
const result = {
|
|
59
|
+
unit: scope === 'system' ? ['After=local-fs.target'] : [] as string[],
|
|
60
|
+
service: ['Type=exec'],
|
|
61
|
+
install: [scope === 'system' ? 'WantedBy=multi-user.target' : 'WantedBy=default.target'],
|
|
62
|
+
};
|
|
59
63
|
if (options.startup !== undefined) {
|
|
60
64
|
const value = options.startup;
|
|
61
65
|
record(value, ['type', 'remainAfterExit', 'timeoutStartSeconds']);
|
|
@@ -67,7 +71,7 @@ export const renderServiceRelations = (options: {
|
|
|
67
71
|
const value = options.dependencies;
|
|
68
72
|
record(value, ['defaultDependencies', 'after', 'before', 'requires', 'wants', 'conflicts']);
|
|
69
73
|
requireValue(typeof value.defaultDependencies === 'boolean');
|
|
70
|
-
const after = [...new Set(['local-fs.target', ...units(value.after)])].sort();
|
|
74
|
+
const after = [...new Set([...(scope === 'system' ? ['local-fs.target'] : []), ...units(value.after)])].sort();
|
|
71
75
|
const before = units(value.before), requires = units(value.requires), wants = units(value.wants), conflicts = units(value.conflicts);
|
|
72
76
|
requireValue(before.every(item => !after.includes(item)) && conflicts.every(item => !requires.includes(item) && !wants.includes(item)));
|
|
73
77
|
result.unit = [`DefaultDependencies=${value.defaultDependencies ? 'yes' : 'no'}`, ...line('After', after),
|