@zowe/cli
Version:
Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.
186 lines • 6.58 kB
JavaScript
"use strict";
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DaemonDecider = void 0;
const fs = require("fs");
const net = require("net");
const os = require("os");
const path = require("path");
const imperative_1 = require("@zowe/imperative");
const DaemonClient_1 = require("./DaemonClient");
const DaemonUtil_1 = require("./DaemonUtil");
// TODO(Kelosky): handle prompting cases from login command
// TODO(Kelosky): prompt* broken - hangs, must restart daemon
// TODO(Kelosky): colors do not come through on some terminals (must be started via `node lib/main --daemon` to see colors)
// TODO(Kelosky): stderr
// TODO(Kelosky): plugins install
/**
* Initial paramter parse to handle conditionally starting as a persistent process (e.g. daemon mode)
* @export
* @class DaemonDecider
*/
class DaemonDecider {
/**
* Creates an instance of DaemonDecider.
* @param {string[]} mParms
* @memberof DaemonDecider
*/
constructor(mParms) {
this.mParms = mParms;
}
/**
* Initialize our DaemonDecider parse and optionally start the server
* @memberof DaemonDecider
*/
init() {
this.initialParse();
if (this.startServer) {
this.mServer = net.createServer((c) => {
new DaemonClient_1.DaemonClient(c, this.mServer, this.mUser).run();
});
this.mServer.on('error', this.error.bind(this));
this.mServer.on('close', this.close.bind(this));
this.recordDaemonPid();
}
}
/**
* Method to immediately parse or otherwise start the server for later processing from
* incoming socket connections.
* @memberof DaemonDecider
*/
runOrUseDaemon() {
if (this.mServer) {
if (process.platform !== "win32" && imperative_1.IO.existsSync(this.mSocket)) {
imperative_1.IO.deleteFile(this.mSocket);
}
["exit", "SIGINT", "SIGQUIT", "SIGTERM"].forEach((eventType) => {
process.on(eventType, this.close.bind(this, true));
});
this.mServer.maxConnections = 1;
this.mServer.listen(this.mSocket, () => {
imperative_1.Imperative.api.appLogger.debug(`daemon server bound ${this.mSocket}`);
new imperative_1.Console(`info`).info(`server bound ${this.mSocket}`);
});
}
else {
imperative_1.Imperative.parse();
}
}
/**
* Record the process ID of the daemon that is being started for the current user.
* On a multi-user system, each user gets his/her own daemon.
*
* @private
* @memberof DaemonDecider
*/
recordDaemonPid() {
const pidForUser = {
user: this.mUser,
pid: process.pid
};
const pidFilePath = path.join(DaemonUtil_1.DaemonUtil.getDaemonDir(), "daemon_pid.json");
const pidForUserStr = JSON.stringify(pidForUser, null, 2);
try {
fs.writeFileSync(pidFilePath, pidForUserStr);
const ownerReadWrite = 0o600;
fs.chmodSync(pidFilePath, ownerReadWrite);
}
catch (err) {
throw new Error("Failed to write file '" + pidFilePath + "'\nDetails = " + err.message);
}
imperative_1.Imperative.api.appLogger.trace("Recorded daemon process ID into " + pidFilePath +
"\n" + pidForUserStr);
}
/**
* Server close handler
* @private
* @memberof DaemonDecider
*/
close(shouldExit) {
imperative_1.Imperative.api.appLogger.debug(`server closed`);
if (shouldExit) {
process.exit();
}
}
/**
* Server error handler
* @private
* @param {Error} err
* @memberof DaemonDecider
*/
error(err) {
imperative_1.Imperative.api.appLogger.error(`daemon server error: ${err.message}`);
throw err;
}
/**
* Perform initial parsing of undocumented parameters
* @private
* @memberof DaemonDecider
*/
initialParse() {
var _a, _b;
if (this.mParms.length > 2) {
/**
* NOTE(Kelosky): For now, we use an undocumented parameter `--daemon`. If found first,
* we bypass `yargs` and begin running this as a persistent Processor.
*/
const parm = this.mParms[2];
const daemonOffset = parm.indexOf(DaemonDecider.DAEMON_KEY);
if (daemonOffset > -1) {
this.startServer = true;
this.mUser = os.userInfo().username;
if (process.platform === "win32") {
this.mUser = this.mUser.toLowerCase();
// On windows we use a pipe instead of a socket
if (((_b = (_a = process.env) === null || _a === void 0 ? void 0 : _a.ZOWE_DAEMON_PIPE) === null || _b === void 0 ? void 0 : _b.length) > 0) {
// user can choose some pipe path
this.mSocket = "\\\\.\\pipe\\" + process.env.ZOWE_DAEMON_PIPE;
}
else {
// use default pipe path name
this.mSocket = `\\\\.\\pipe\\${this.mUser}\\ZoweDaemon`;
}
}
else {
// Linux-like systems use domain sockets
this.mSocket = path.join(DaemonUtil_1.DaemonUtil.getDaemonDir(), "daemon.sock");
}
imperative_1.Imperative.api.appLogger.debug(`daemon server will listen on ${this.mSocket}`);
}
}
}
/**
* Get whether or not to start the server
* @private
* @memberof DaemonDecider
*/
get startServer() {
return this.mStartServer;
}
/**
* Set whether or not to start the server
* @private
* @memberof DaemonDecider
*/
set startServer(startServer) {
this.mStartServer = startServer;
}
}
exports.DaemonDecider = DaemonDecider;
/**
* Undocumented paramter for launching in server mode
* @private
* @static
* @memberof DaemonDecider
*/
DaemonDecider.DAEMON_KEY = "--daemon";
//# sourceMappingURL=DaemonDecider.js.map