diff options
| author | Klaatu Sverige <[email protected]> | 2015-08-05 21:31:21 +0000 |
|---|---|---|
| committer | Klaatu Sverige <[email protected]> | 2015-08-05 21:31:21 +0000 |
| commit | 86f0721bd904d8163c5f8f2472b78169146cc67d (patch) | |
| tree | cf9e61bd495c73ece45b96242e6f575af228d01d /riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty-helper.c | |
| parent | 75a501d32dff3c1c1ee9a2a3dc6d5b704cc7c6d1 (diff) | |
added website data, because it had heaps of good tutorials and info
Diffstat (limited to 'riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty-helper.c')
| -rw-r--r-- | riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty-helper.c | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty-helper.c b/riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty-helper.c new file mode 100644 index 0000000..a368b7a --- /dev/null +++ b/riemann.fmi.uni-sofia.bg/ngetty/ngetty-1.1/ngetty-helper.c @@ -0,0 +1,335 @@ +#define _GNU_SOURCE + +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <alloca.h> +#include <errno.h> +#include <termios.h> +#include <sys/utsname.h> +#include <sys/ioctl.h> +#include <sys/param.h> +#include "lib.h" +#include "opts_defs.h" + +/* most of the functions here (like str_copy, fmt_ulong) + have manual pages in libowfat; http://www.fefe.de/ + see also opts_defs.h for o[Oxxx]; man ngetty */ + +/* see out_put.c; man buffer */ +#define outs(X) out_puts(X) +#define GO_out "go out!" + +static struct utsname uts; +static struct stat st; +static char *tty, *o_opt, o_endchar; +char **Oo = o; /* see opts_defs.h */ + +static void tty_flush() { ioctl(0, TCFLSH, TCIFLUSH); } + +/* Format of o[Oprint]: ab:cq:09:AZ:...; man ngetty + return -1 if 'ch' does not belongs to the set o[Oprint]; 0 success */ +static int char_allow(unsigned char ch) { + unsigned char c0, c1, *x = (unsigned char *)o[Oprint]; + again: + c0 = x[0]; if (!c0) return -1; + c1 = x[1]; if (!c1) return -1; + if (c0 <= ch && ch <= c1) return 0; + if (x[2] == ':') { x += 3; goto again; } + return -1; +} + +/* print maximal 'len' chars from 's'; see strncpy, snprintf, printf */ +static void out_max(char *s, unsigned int len) { + char c = 0; + if (s == uts.nodename && !o[Olonghostname]) c = '.'; + while (len && *s && *s != c) { + out_char(*s); ++s; --len; + } +} + +#define Out_MAX(X) x=X; len=sizeof(X); goto system + +/* print string with escapes; man ngetty; man issue */ +static void output_special_char(char *s, int len) { + char *last = s + len; + while (s < last) { + char *x, c; + if (*s != '\\') { out_char(*s); ++s; continue; } + if (++s == last) return; + + c = *s++; + switch (c) { + case 's': Out_MAX(uts.sysname); + case 'n': Out_MAX(uts.nodename); + case 'r': Out_MAX(uts.release); + case 'v': Out_MAX(uts.version); + case 'm': Out_MAX(uts.machine); + case 'o': Out_MAX(uts.domainname); + system: + out_max(x,len); break; + case 'l': + outs(tty); break; +#ifndef DONT_NEED_ESC_TIME + case 't': + x = "H:M:S"; goto do_time; + case 'd': + x = (o[Odatestring]) ? "a b d Y" : "Y-m-d"; + do_time: + fmt_time(x); break; +#endif +#ifndef DONT_NEED_ESC_USERS + case 'u': + case 'U': + { + char ubuf[8 + 3*sizeof(unsigned long)], *x = ubuf; + unsigned long usrs = utmp_users(); + x += fmt_ulong(x, usrs); + if (c=='U') { + x += str_copynz(x, " users", 10); + if (usrs==1) --x; + } + *x = 0; + outs(ubuf); + } + break; +#endif + default: + if (s+1 < last) { + unsigned char uch = (unsigned char)c-'0'; + if (uch < 4) { /* XXX \0xy is not tested */ + c = (uch<<6) | ((s[0]-'0')<<3) | (s[1]-'0'); + s += 2; + } + } + out_char(c); + } + } +} + +/* print string 's' with escapes; man ngetty */ +static void Out_sp_ch(char *s) { output_special_char(s, str_len(s)); } + +/* exception: print string 's' and exit with status 'i' */ +void error(char *s,int i) { + struct timespec ts = { 2, 500111222 }; + Out_sp_ch("\nngetty-helper: \\d \\t \\l: "); + outs(s); out_char('\n'); out_flush(); + nanosleep(&ts, 0); + tty_flush(); + _exit(i); +} + +/* print /etc/issue and login prompt; man issue */ +static void do_prompt() { + int fd,len; + char *s; + Out_sp_ch(o[Onewline]); + s = o[Oissuefile]; + if (s[0] && (fd=open(s, O_RDONLY)) >= 0) { + if (GLOBAL_fstat_READ(fd,st,s, len,64000, 1)) _exit(1); + close(fd); + output_special_char(s, len); + } + Out_sp_ch(o[Ologinprompt]); + out_flush(); +} + +/* get login name in logname. max length = last-logname + man ngetty; options: login-buffer, timeout */ +static void get_logname(char *logname, char *last) { + char *c; + alarm(x_atoi(o[Otimeout])); + for (;;) { + for (c=logname;; c++) { + if (c == last) + error("login name too long",11); + if (read(0,c,1)<1) { + if (errno==EINTR || errno==EIO || errno==ENOENT) + _exit(0); + error("received strange error",9); + } + if (*c == '\n' || *c == '\r') { + *c=0; + break; + } + if (char_allow((unsigned char)*c)) + error("bad character in login name",10); + } /* end read */ + if (*logname == '-') + error("username may not start with a dash",13); + if (*logname) break; + do_prompt(); + } + alarm(0); +} + +/* parse string; store it in o[XXX]; see opts_defs.h; /etc/ngetty/Conf */ +static char *opt_get(char *s, int len) { + if (*o_opt == *s) { + char *x = o_opt; + if (!str_diffn(x,s,len) && x[len] == o_endchar) { + if (o[Odebug] && s != tty) { + outs(x - 1); + out_char('\n'); + } + return x+len+1; + } + } + return 0; +} + +/* return 1 if user is in s, otherwise 0; + Format of s: ,ab,uvw,MlqR, ... ,last */ +static char in_list(char *s, const char *user) { + char ch; + int len; + if (s==0 || *s==0 || user==0) return 0; + len = str_len(user); + ch = *s++; + again: + if (!str_diffn(s,user,len)) + if (s[len]==ch || s[len]==0) return 1; + while (*s && *s != ch) s++; + if (*s++) goto again; + return 0; +} + +/* set controlling tty */ +static void set_ctty() { + if (setsid() == -1 || ioctl(0, TIOCSCTTY, (void *)1)) + error(GO_out, 111); +} + +int main(int argc,char *argv[]) { + int fd,len; + char *s; + struct termios term; + if (argc < 2) _exit(100); + + o[Oautologinfirst] = o[Onoclearfirst] = o[Oautologinname] = ""; + o[Oissuefile] = "/etc/issue"; + o[Ologinprog] = LOGIN; + o[Oprint] = "az:AZ:09:,.:__"; + o[Otimeout] = "180"; + o[Ologinprompt] = "\\n login: "; + o[Onewline] = "\n"; + o[Oclear] = "\033c"; +#ifndef DONT_NEED_ESC_TIME + o[Omonths] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + o[Odays] = "SunMonTueWedThuFriSat"; + o[Otz] = "/etc/localtime"; +#endif + + tty = argv[1]; + uname(&uts); + if (dup(0) !=1 || dup(0) !=2 || ioctl(0,TCGETS,&term)) error(GO_out, 100); + if (!str_diffn(tty, "/dev/", 5)) tty += 5; + + if ((fd = open(NGETTY_HOME "/Conf", O_RDONLY)) >=0) { + char **aa=0, *q; + int tty_len = str_len(tty); + /* 40 bytes for Months or Days */ + if (GLOBAL_fstat_READ(fd,st,s, len,64000, 40)) _exit(1); + close(fd); + if (st.st_uid || st.st_gid || (st.st_mode & 07177)) len = 0; + s[len]=0; + + GLOBAL_split(aa,s,'\n', len); + + for (; *aa; aa++) { + s=aa[0]; + if (*s==0 || *s=='#' || *s=='\t' || *s==' ') continue; + + o_endchar = '='; + if (*s=='=') o_opt = s+1; + else { + o_opt = s; + if (!(o_opt = opt_get(tty, tty_len))) continue; + } + + for (len=0, q=(char *)P_opt; len < MAX_options; len++) { + int k = P_len[len]; + if (len >= MAX_equal) o_endchar = 0; + if ((s = opt_get(q, k))) { o[len] = s; break; } + q += k; + } + } + } + + if ((s=o[Onice])) nice(x_atoi(s)); + + if ((s=o[Oenviron])) { + char **ee=0, ch=*s++; + if (ch) GLOBAL_split(ee,s,ch, len); + environ=ee; + } + + if (argc>2 && argv[2][0] == 'l') { /* get logname and execve() login */ + char *loginargv[]={ o[Ologinprog], "--", 0, 0, 0 }; + fork_and_exec(o[OshB]); + + s = o[Oautologinfirst]; + if (*s && !check_first(s,&st)) o[Oautologinname] = ""; + + s = o[Oautologinname]; + if (*s) { + loginargv[1] = "-f"; + loginargv[2] = s; + } else { + o[Oissuefile] = ""; + if (!o[Onousername]) { + char *last, *buf = o[Ologinbuffer]; + if (buf) last = buf + str_len(buf); + else { buf = alloca(41); last = buf + 40; } + loginargv[2] = buf; + get_logname(buf, last); + } + } + + if (o[Oechooff]) { + term.c_lflag &= ~(ECHO|ISIG); + ioctl(0, TCSETS, &term); + } + + if ((s=o[Ologinargv])) { + loginargv[1] = s; /* change '--' or '-f' with login-argv */ + loginargv[3] = tty; + } + + s = loginargv[2]; + if (in_list(o[Odeny],s) || + (o[Oallow] && in_list(o[Oallow],s)==0)) + error("login is disabled",14); + + out_flush(); + tty_flush(); + utmp_do(1,tty); + + if ((s=o[Ochroot])) chroot(s); + if ((s=o[Ochdir])) chdir(s); + set_ctty(); + execve(*loginargv, loginargv, environ); + } else { /* print /etc/issue and exit */ + char *clear = o[Oclear]; + tty_flush(); + + fork_and_exec(o[OshA]); + if ((s=o[Odelay])) { + struct timespec ts = { x_atoi(s), 100200300 }; + nanosleep(&ts, 0); + } + + s = o[Onoclearfirst]; + if (*s && check_first(s,&st)) clear = ""; + + Out_sp_ch(clear); + utmp_do(0,tty); + do_prompt(); + +#ifdef HAVE_SYSTEM_VHANGUP + if (!o[Onohangup]) { set_ctty(); vhangup(); } +#endif + } + _exit(0); +} |
