<commit_before>/* New client tool, replaces old /dev/initctl API and telinit tool
 *
 * Copyright (c) 2015-2022  <NAME> <<EMAIL>>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "config.h"

#include <ftw.h>
#include <ctype.h>
#include <getopt.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <utmp.h>
#include <arpa/inet.h>
#ifdef _LIBITE_LITE
# include <libite/lite.h>
#else
# include <lite/lite.h>
#endif

#include "initctl.h"
#include "client.h"
#include "cond.h"
#include "serv.h"
#include "service.h"
#include "cgutil.h"
#include "util.h"
#include "utmp-api.h"

struct cmd {
	char        *cmd;
	struct cmd  *ctx;
	int        (*cb)(char *arg);
	int         *cond;
	int        (*cb_multiarg)(int argc, char **argv);
};

int icreate  = 0;
int iforce   = 0;
int ionce    = 0;
int debug    = 0;
int heading  = 1;
int verbose  = 0;
int plain    = 0;
int quiet    = 0;
int runlevel = 0;
int cgrp     = 0;
int utmp     = 0;

int iw, pw;

extern int reboot_main(int argc, char *argv[]);


/* figure ut width of IDENT and PID columns */
static void col_widths(void)
{
	char ident[MAX_IDENT_LEN];
	char pid[10];
	svc_t *svc;

	iw = 0;
	pw = 0;

	for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
		int w, p;

		svc_ident(svc, ident, sizeof(ident));
		w = (int)strlen(ident);
		if (w > iw)
			iw = w;

		p = snprintf(pid, sizeof(pid), "%d", svc->pid);
		if (p > pw)
			pw = p;
	}

	/* adjust for min col width */
	if (iw < 5)
		iw = 5;
	if (pw < 3)
		pw = 3;
}

void print_header(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);

	if (plain) {
		int len;

		vfprintf(stdout, fmt, ap);
		fputs("\n", stdout);
		for (len = 0; len < ttcols; len++)
			fputc('=', stdout);
		fputs("\n", stdout);
	} else {
		char buf[ttcols];

		vsnprintf(buf, sizeof(buf), fmt, ap);
		printheader(stdout, buf, 0);
	}

        va_end(ap);
}

static int runlevel_get(int *prevlevel)
{
	struct init_request rq;
	int rc;

	rq.cmd = INIT_CMD_GET_RUNLEVEL;
	rq.magic = INIT_MAGIC;

	rc = client_send(&rq, sizeof(rq));
	if (!rc) {
		rc = rq.runlevel;
		if (prevlevel)
			*prevlevel = rq.sleeptime;
	}

	return rc;
}

static int toggle_debug(char *arg)
{
	struct init_request rq = {
		.magic = INIT_MAGIC,
		.cmd = INIT_CMD_DEBUG,
	};

	return client_send(&rq, sizeof(rq));
}

static int do_log(svc_t *svc, char *tail)
{
	const char *logfile = "/var/log/syslog";
	char *nm = svc_ident(svc, NULL, 0);
	pid_t pid = svc->pid;

	if (!nm || !nm[0]) {
		nm  = "finit";
		pid = 1;
	}

	if (!fexist(logfile)) {
		logfile = "/var/log/messages";
		if (!fexist(logfile))
			return 0; /* bail out, maybe in container */
	}

	return systemf("cat %s | grep '\\[%d\\]\\|%s' %s", logfile, pid, nm, tail);
}

/* initctl log [-10] foo */
static int show_log(char *arg)
{
	svc_t *svc;

	svc = client_svc_find(arg);
	if (!svc)
		return 255;

	return do_log(svc, "");
}

static int do_runlevel(char *arg)
{
	struct init_request rq = {
		.magic = INIT_MAGIC,
		.cmd = INIT_CMD_RUNLVL,
	};

	if (!arg) {
		int prevlevel = 0;
		int currlevel;
		char prev;

		currlevel = runlevel_get(&prevlevel);
		if (255 == currlevel) {
			printf("unknown\n");
			return 0;
		}<commit_msg>initctl: fix fallback handling in log command<commit_after>/* New client tool, replaces old /dev/initctl API and telinit tool
 *
 * Copyright (c) 2015-2022  <NAME> <<EMAIL>>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "config.h"

#include <ftw.h>
#include <ctype.h>
#include <getopt.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <utmp.h>
#include <arpa/inet.h>
#ifdef _LIBITE_LITE
# include <libite/lite.h>
#else
# include <lite/lite.h>
#endif

#include "initctl.h"
#include "client.h"
#include "cond.h"
#include "serv.h"
#include "service.h"
#include "cgutil.h"
#include "util.h"
#include "utmp-api.h"

struct cmd {
	char        *cmd;
	struct cmd  *ctx;
	int        (*cb)(char *arg);
	int         *cond;
	int        (*cb_multiarg)(int argc, char **argv);
};

int icreate  = 0;
int iforce   = 0;
int ionce    = 0;
int debug    = 0;
int heading  = 1;
int verbose  = 0;
int plain    = 0;
int quiet    = 0;
int runlevel = 0;
int cgrp     = 0;
int utmp     = 0;

int iw, pw;

extern int reboot_main(int argc, char *argv[]);


/* figure ut width of IDENT and PID columns */
static void col_widths(void)
{
	char ident[MAX_IDENT_LEN];
	char pid[10];
	svc_t *svc;

	iw = 0;
	pw = 0;

	for (svc = client_svc_iterator(1); svc; svc = client_svc_iterator(0)) {
		int w, p;

		svc_ident(svc, ident, sizeof(ident));
		w = (int)strlen(ident);
		if (w > iw)
			iw = w;

		p = snprintf(pid, sizeof(pid), "%d", svc->pid);
		if (p > pw)
			pw = p;
	}

	/* adjust for min col width */
	if (iw < 5)
		iw = 5;
	if (pw < 3)
		pw = 3;
}

void print_header(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);

	if (plain) {
		int len;

		vfprintf(stdout, fmt, ap);
		fputs("\n", stdout);
		for (len = 0; len < ttcols; len++)
			fputc('=', stdout);
		fputs("\n", stdout);
	} else {
		char buf[ttcols];

		vsnprintf(buf, sizeof(buf), fmt, ap);
		printheader(stdout, buf, 0);
	}

        va_end(ap);
}

static int runlevel_get(int *prevlevel)
{
	struct init_request rq;
	int rc;

	rq.cmd = INIT_CMD_GET_RUNLEVEL;
	rq.magic = INIT_MAGIC;

	rc = client_send(&rq, sizeof(rq));
	if (!rc) {
		rc = rq.runlevel;
		if (prevlevel)
			*prevlevel = rq.sleeptime;
	}

	return rc;
}

static int toggle_debug(char *arg)
{
	struct init_request rq = {
		.magic = INIT_MAGIC,
		.cmd = INIT_CMD_DEBUG,
	};

	return client_send(&rq, sizeof(rq));
}

static int do_log(svc_t *svc, char *tail)
{
	const char *logfile = "/var/log/syslog";
	pid_t pid;
	char *nm;

	if (svc) {
		nm = svc_ident(svc, NULL, 0);
		pid = svc->pid;
	} else {
		nm  = "finit";
		pid = 1;
	}

	if (!fexist(logfile)) {
		logfile = "/var/log/messages";
		if (!fexist(logfile))
			return 0; /* bail out, maybe in container */
	}

	return systemf("cat %s | grep '\\[%d\\]\\|%s' %s", logfile, pid, nm, tail);
}

static int show_log(char *arg)
{
	svc_t *svc = NULL;

	if (arg) {
		svc = client_svc_find(arg);
		if (!svc)
			return 255;
	}

	return do_log(svc, "");
}

static int do_runlevel(char *arg)
{
	struct init_request rq = {
		.magic = INIT_MAGIC,
		.cmd = INIT_CMD_RUNLVL,
	};

	if (!arg) {
		int prevlevel = 0;
		int currlevel;
		char prev;

		currlevel = runlevel_get(&prevlevel);
		if (255 == currlevel) {
			printf("unknown\n");
			return 0;
		}
{'fraction_non_alphanumeric': 0.13903932187426418, 'fraction_numerical': 0.010242524134683306, 'mean_word_length': 3.3901808785529717, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3773186', 'n_tokens_mistral': 3469, 'n_tokens_neox': 3199, 'n_words': 1043}