summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsinanmohd <sinan@firemail.cc>2023-05-22 15:25:25 +0530
committersinanmohd <sinan@firemail.cc>2023-06-26 12:59:10 +0530
commitd7ce046606ce05dd8a37e83fc48667bbe4c20093 (patch)
tree7e8d44431998e8c9d80f39165b6525866ddb5856
initial commitHEADmaster
-rw-r--r--.gitignore2
-rw-r--r--Makefile14
-rw-r--r--TODO4
-rw-r--r--config.h9
-rw-r--r--main.c89
-rw-r--r--menu.c117
-rw-r--r--menu.h3
-rw-r--r--ui.c129
-rw-r--r--ui.h10
-rw-r--r--util.c22
-rw-r--r--util.h26
11 files changed, 425 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9d613b8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+tuil
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a16e712
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+OBJECTS = main.o util.o ui.o menu.o
+CC = gcc
+CFLAGS = -g -Wvla -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -Wpedantic -fsanitize=address
+
+tuil: $(OBJECTS)
+ $(CC) $(CFLAGS) -o tuil $(OBJECTS)
+
+main.o: config.h menu.h util.h
+menu.o: ui.h util.h
+ui.o: util.o config.h
+
+.PHONY: clean
+clean:
+ rm -f tuil $(OBJECTS)
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..2fef041
--- /dev/null
+++ b/TODO
@@ -0,0 +1,4 @@
+remove controling term with ioctl
+back fall to stdin
+use buf to communicate with child
+gets status
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..b97716d
--- /dev/null
+++ b/config.h
@@ -0,0 +1,9 @@
+#define MAX_PASS 128
+#define MAX_STATUS 128
+
+static const char statverf = '.';
+static const char statfail = ',';
+static const char statstr[] = "_-";
+static const char headpromt[] = "Authentication Required";
+static const char headverf[] = "Verifying";
+static const char headerr[] = "Authentication Failed";
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..1a9d483
--- /dev/null
+++ b/main.c
@@ -0,0 +1,89 @@
+#include <unistd.h>
+
+#include "menu.h"
+#include "ui.h"
+#include "config.h"
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int errflg, fd, rc;
+ char c;
+
+ State state = {
+ .headerr = headerr,
+ .headverf = headverf,
+ .statstr = statstr,
+ .statverf = statverf,
+ .statfail = statfail,
+ .cmds[PASS].name = headpromt
+ };
+
+ errflg = 0;
+ while ((c = getopt(argc, argv, "ip:e:v:s:r:l:c:u:d:w:")) != -1) {
+ switch(c) {
+ case 'i':
+ state.flag |= IGNORE_ISIG;
+ break;
+ case 'p':
+ state.cmds[PASS].name = optarg;
+ break;
+ case 'e':
+ state.headerr = optarg;
+ break;
+ case 'v':
+ state.headverf = optarg;
+ break;
+ case 's':
+ state.statstr = optarg;
+ break;
+ case 'r':
+ state.statverf = *optarg;
+ break;
+ case 'l':
+ state.statfail = *optarg;
+ break;
+ case 'c':
+ state.cmds[PASS].cmd = optarg;
+ break;
+ case 'u':
+ state.cmds[UP].name = optarg;
+
+ while (*optarg && *optarg != '=')
+ optarg++;
+ if (*optarg == '=')
+ state.cmds[UP].cmd = optarg + 1;
+ else
+ errflg++;
+
+ *optarg = '\0';
+ break;
+ case 'd':
+ state.cmds[DOWN].name = optarg;
+
+ while (*optarg && *optarg != '=')
+ optarg++;
+ if (*optarg == '=')
+ state.cmds[DOWN].cmd = optarg + 1;
+ else
+ errflg++;
+
+ *optarg = '\0';
+ break;
+ case 'w':
+ state.floc = optarg;
+ break;
+ case '?':
+ errflg++;
+ }
+ }
+
+ if (errflg || !state.cmds[PASS].cmd)
+ die("usage: tuil [-ipevsrl]");
+
+ fd = uiinit(&state);
+ rc = menuinit(&state, fd) - 1;
+ uicleanup();
+
+ return rc;
+}
diff --git a/menu.c b/menu.c
new file mode 100644
index 0000000..b73c745
--- /dev/null
+++ b/menu.c
@@ -0,0 +1,117 @@
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "menu.h"
+#include "ui.h"
+#include "util.h"
+
+#define MAX_PASS 128
+#define NO_OPT 0
+
+static char pass[MAX_PASS];
+
+static int getip(const State *state, int fd);
+static pid_t run(const char *cmd);
+static void updatestat(const State *state, unsigned typ, int pos);
+
+int menuinit(const State *state, int fd)
+{
+ int rc, wfd = -1, status = 0;
+ pid_t pid;
+
+ if (state->floc)
+ if ((wfd = open(state->floc, O_WRONLY | O_CREAT)) == -1)
+ die ("can't open %s", state->floc);
+
+ do {
+ if (WEXITSTATUS(status))
+ pui(state->headerr, state->statfail);
+ else
+ pui(state->cmds[PASS].name, state->statstr[0]);
+
+ rc = getip(state, fd);
+
+ if (wfd >= 0 && rc == PASS)
+ write(wfd, pass, strlen(pass));
+
+ pid = run(state->cmds[rc].cmd);
+ if (rc == PASS) {
+ pui(state->headverf, state->statverf);
+ waitpid(pid, &status, NO_OPT);
+ }
+ } while (WEXITSTATUS(status) || rc != PASS);
+
+ if (wfd >= 0)
+ close(wfd);
+
+ return rc;
+}
+
+static int getip(const State *state, int fd)
+{
+ unsigned i;
+ int rc, floor, ceil;
+
+ rc = floor = ceil = PASS;
+ if (state->cmds[DOWN].name)
+ floor = DOWN;
+ if (state->cmds[UP].name)
+ ceil = UP;
+
+ for (i = 0; i + 1 < MAX_PASS; ) {
+ read(fd, pass + i, 1);
+
+ if (pass[i] == DEL) {
+ if (i > 0)
+ --i;
+ } else if (pass[i] == NL) {
+ break;
+ } else if (i >= 2 && pass[i-2] == ESC && pass[i-1] == '[' ) {
+ if (pass[i] == 'A' && rc < ceil)
+ ++rc;
+ else if (pass[i] == 'B' && rc > floor)
+ --rc;
+ i -= 2;
+ } else {
+ ++i;
+ }
+
+ pheader(state->cmds[rc].name);
+ updatestat(state, rc, i);
+ }
+
+ pass[i] = '\0';
+ return rc;
+}
+
+static void updatestat(const State *state, unsigned typ, int pos)
+{
+ if (typ == PASS) {
+ if (pos)
+ genrandstat(state->cmds[PASS].name, state->statstr);
+ else
+ pstaticstat(state->cmds[PASS].name, state->statstr[0]);
+ } else {
+ pstaticstat(state->cmds[typ].name, state->statverf);
+ }
+}
+
+static pid_t run(const char *cmd)
+{
+ pid_t pid;
+
+ if ((pid = fork()) == 0) {
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ execlp("sh", "sh", "-c", cmd, NULL);
+ die("run: fork(): %s", cmd);
+ }
+
+ return pid;
+}
diff --git a/menu.h b/menu.h
new file mode 100644
index 0000000..de5bda5
--- /dev/null
+++ b/menu.h
@@ -0,0 +1,3 @@
+#include "util.h"
+
+int menuinit(const State *state, int fd);
diff --git a/ui.c b/ui.c
new file mode 100644
index 0000000..4578240
--- /dev/null
+++ b/ui.c
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <fcntl.h>
+
+#include "util.h"
+#include "ui.h"
+
+#define MAX_STATUS 128
+
+static char stbuf[MAX_STATUS];
+
+static unsigned short rows;
+static unsigned short cols;
+static struct termios prevstate;
+static int tty_fd;
+
+int uiinit(const State *state)
+{
+ struct winsize w;
+ struct termios t;
+
+ if ((tty_fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
+ die("getpass: can't open /dev/tty for input");
+
+ tcgetattr(tty_fd, &t);
+ prevstate = t;
+ if (state->flag & IGNORE_ISIG)
+ t.c_lflag &= ~(ISIG);
+ t.c_lflag &= ~(ECHO|INLCR|IGNCR|ICANON);
+ t.c_iflag |= ICRNL;
+ tcsetattr(tty_fd, TCSAFLUSH, &t);
+ tcdrain(tty_fd);
+
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &w) == -1)
+ die("ioctl() failed");
+
+ rows = w.ws_row;
+ cols = w.ws_col;
+
+ printf("%c7", ESC); /* save cursor */
+ printf("%c[?47h", ESC); /* use alt buffer */
+ printf("%c[?25l", ESC); /* hide cursor */
+ printf("%c[2J", ESC); /* clear vt */
+
+ return tty_fd;
+}
+
+void pheader(const char *s)
+{
+ unsigned short col, row;
+
+ row = rows / 2;
+ col = (cols - strlen(s)) / 2;
+
+ printf("%c[%d;%dH", ESC, row, col); /* pos curosr */
+ printf("%c[2K", ESC); /* clear line */
+ puts(s);
+}
+
+void pstatus(const char *s)
+{
+ unsigned short col, row;
+
+ row = rows / 2 + 1;
+ col = (cols - strlen(s)) / 2;
+
+ printf("%c[%d;%dH", ESC, row, col); /* pos cursor */
+ printf("%c[2K", ESC); /* clear line */
+ puts(s);
+}
+
+void pstaticstat(const char *head, const char c)
+{
+ size_t stlen;
+
+ if ((stlen = strlen(head)) > MAX_STATUS - 1)
+ stlen = MAX_STATUS - 1;
+ stbuf[stlen] = '\0';
+
+ memset(stbuf, c, stlen);
+ pstatus(stbuf);
+}
+
+void genrandstat(const char *head, const char *statstr)
+{
+ int entropy;
+ size_t srlen, stlen, i;
+
+ if ((stlen = strlen(head)) > MAX_STATUS - 1)
+ stlen = MAX_STATUS - 1;
+ srlen = strlen(statstr);
+
+ for (entropy = i = 0; i < stlen; ++i, entropy /= srlen) {
+ if (!entropy)
+ entropy = rand();
+
+ stbuf[i] = statstr[entropy % srlen];
+ }
+
+ stbuf[stlen] = '\0';
+ pstatus(stbuf);
+}
+
+void uicleanup(void)
+{
+ printf("%c[2J", ESC); /* clear vt */
+ printf("%c[?25h", ESC); /* show cursor */
+ printf("%c[?47l", ESC); /* use normal buffer */
+ printf("%c8", ESC); /* restore cursor */
+
+ tcsetattr(tty_fd, TCSAFLUSH, &prevstate);
+ close(tty_fd);
+}
+
+void pui(const char *head, const char stat)
+{
+ size_t stlen;
+
+ if ((stlen = strlen(head)) > MAX_STATUS - 1)
+ stlen = MAX_STATUS - 1;
+ stbuf[stlen] = '\0';
+
+ pheader(head);
+ pstatus(memset(stbuf, stat, stlen));
+}
diff --git a/ui.h b/ui.h
new file mode 100644
index 0000000..3cde7fe
--- /dev/null
+++ b/ui.h
@@ -0,0 +1,10 @@
+#include <stddef.h>
+#include "util.h"
+
+int uiinit(const State *state);
+void pheader(const char *s);
+void pstatus(const char *s);
+void genrandstat(const char *head, const char *statstr);
+void pui(const char *head, const char stat);
+void pstaticstat(const char *head, const char c);
+void uicleanup(void);
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..d8c65b8
--- /dev/null
+++ b/util.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include "util.h"
+
+void die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, fmt, ap);
+ if (errno)
+ fprintf(stderr, " (%d): %s\n", errno, strerror(errno));
+ else
+ fputc('\n', stderr);;
+ va_end(ap);
+
+ exit(errno);
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..41f2e28
--- /dev/null
+++ b/util.h
@@ -0,0 +1,26 @@
+#ifndef UTIL_H
+
+enum ascii { NL = 10, ESC = 27, DEL = 127 };
+enum flags { IGNORE_ISIG = 1 << 0 };
+enum iptyp { DOWN = 0, PASS = 1, UP = 2 };
+
+typedef struct {
+ const char *name;
+ const char *cmd;
+} Menu;
+
+typedef struct {
+ int flag;
+ char statverf;
+ char statfail;
+ const char *headverf;
+ const char *headerr;
+ const char *statstr;
+ const char *floc;
+ Menu cmds[3];
+} State;
+
+void die(const char *fmt, ...);
+
+#define UTIL_H
+#endif