diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | index.css | 91 | ||||
-rw-r--r-- | index.php | 134 | ||||
-rw-r--r-- | lastlog.c | 145 | ||||
-rwxr-xr-x | userbar.sh | 10 |
6 files changed, 401 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c5ad59f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +index.html +lastlog.html +userbar.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df17a33 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +default: + @echo Not doing anything by default to prevent you from messing up a local checkout. + @echo If you are on a local checkout: build this on town, copy over userbar.html and + @echo lastlog.html, and run php -S localhost:8000 + +lastlog: lastlog.c + cc -o lastlog -Wall -Wextra lastlog.c -lm + +.PHONY: userbar.html +userbar.html: userbar.sh + ./userbar.sh > userbar.html + +.PHONY: lastlog.html +lastlog.html: lastlog + ./lastlog > lastlog.html + +index.html: lastlog.html userbar.html + php index.php > index.html diff --git a/index.css b/index.css new file mode 100644 index 0000000..15415cb --- /dev/null +++ b/index.css @@ -0,0 +1,91 @@ +* { + box-sizing: border-box; +} + +body { + background: black; + color: white; + display: flex; + flex-wrap: nowrap; + justify-content: center; + line-height: 1.5; + font-family: monospace; + font-size: 1rem; +} + +main { + max-width: 80ch; + order: 0; +} + +#users { + width: 20ch; + text-align: right; + order: -1; + margin-right: 1em; + overflow: hidden; +} + +#right { + width: 50ch; +} + +@media (max-width: 150ch) { #right { display: none; } } +@media (max-width: 100ch) { #users { display: none; } } + + +#users ul { + margin: 0; + list-style: none; +} + +#heatmap { + position: absolute; + max-width: 80ch; + z-index: -100; +} + +#heatmap a { + width: .75em; + height: .75em; + display: inline-block; + border-radius: 100%; + margin: .25em; +} + +.box { + background: #0c0a0fc0; + box-shadow: 5px 5px 5px #0c0a0fc0; + padding: 1em 1.5ch; + display: inline-block; + margin: .5em; +} + +main > *:not(#heatmap) { + margin: 1em; +} + +pre, p { + margin: 0; +} + +a { + color: #b5d0f4; +} + +#users a { + color: #5e7ea8; +} + +#right > * { + width : 100%; +} + +#planet ul { + margin-left: 1ch; +} + +.planetuser { + float: right; + opacity: 0.7; +} diff --git a/index.php b/index.php new file mode 100644 index 0000000..0165fe8 --- /dev/null +++ b/index.php @@ -0,0 +1,134 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=0.5, user-scalable=yes" /> + <!-- <link href="index.css" rel="stylesheet" /> --> + <style> <?php include 'index.css'; ?> </style> +</head> + +<body> + +<main> +<div id="heatmap"> <?php include 'lastlog.html'; ?> </div> +<div class="box"> <pre> + _ + o | | | +_|_ | | __| _ _|_ __ _ _ + | | |/ / | |/ | / \_| | |_/ |/ | + |_/|_/|__/\_/|_/|__/o|_/\__/ \/ \/ | |_/ + is a computer meant for sharing +</pre> </div> +<div class="box" style="float:right; text-align:right;"> <pre> +<a href="#aa">helpdesk</a> +<a href="#aa">wiki</a> +<a href="#aa">blog</a> +<a href="#aa">cgit</a> +<a href="#aa">gitea</a> +<a href="#aa">testimonials</a> +</pre> </div> + +<div class="box"> +we are a <b>community</b> of around <a href="#">3000 users</a> making art, socializing, and learning on a linux server. +founded in 2014 by <a href="/~vilmibm">~vilmibm</a>. +</div> + +<!-- +<div style="float:right" class="box"> <pre> + _____________________________________________ +| __ : | +| / /\ __ ___!__ _,__ ___,_ | +|/ / o\/ \ / /\ /__/ \ /__\__\ . . | +| / \\ \/_____ /_*\ | |[^][^| | |[^]())| +|/ /\ | | |_|__| .: |__|__| ()(/| +| || | {^} | | ( ~)(| +| [] [] | | | |. . A ._ . .( O((/| +| _ _ |___|__|__D_| . H / \ {^} ()||)| +| | |[@] | | . . . | |/ \ | \|| | +|_|_|_____| . . |^| \ | v ||/| +| . . v v . | | \|. v /v| +| . v v . / O \ /| . /vv| +| |_ u _| . . / _ \ / | .. | +| || | || / |_| \/ | . | +|___________<span style="opacity:.5">by <a href="#aa">~sanqui</a></span>________________________| +</pre> </div> +--> + +<div class="box"> +here's some stuff made by townies: +<ul> +<li><a href="#aa">music</a></li> +<li><a href="#aa">a zine</a></li> +<li><a href="#aa">interactive art</a></li> +<li><a href="#aa">technical guides</a></li> +<li><a href="#aa">a babby</a></li> +</ul> +</div> + +<div class="box"> +<p> if you think you might enjoy being a part of this community you can <a href="#aa">learn more here</a>. </p> +</div> + + +<div class="box"> +<p> every dot in the background represents one townie. the more recently were they active, the brighter the dot. +imagine there's a button to click that hides all this shit and lets you explore the map. </p> +</div> + +<div class="box"> <pre> +ecdsa host key: SHA256:RGr0EXrHOCt/ZZitfMK2WFwbI80OGzat+DlthhTfWf4 +</pre> </div> + +</main> + +<aside id="right"> +<div class="box"> <pre> + _____________________________________________ +| __ : | +| / /\ __ ___!__ _,__ ___,_ | +|/ / o\/ \ / /\ /__/ \ /__\__\ . . | +| / \\ \/_____ /_*\ | |[^][^| | |[^]())| +|/ /\ | | |_|__| .: |__|__| ()(/| +| || | {^} | | ( ~)(| +| [] [] | | | |. . A ._ . .( O((/| +| _ _ |___|__|__D_| . H / \ {^} ()||)| +| | |[@] | | . . . | |/ \ | \|| | +|_|_|_____| . . |^| \ | v ||/| +| . . v v . | | \|. v /v| +| . v v . / O \ /| . /vv| +| |_ u _| . . / _ \ / | .. | +| || | || / |_| \/ | . | +|___________<span style="opacity:.5">by <a href="#aa">~sanqui</a></span>________________________| +</pre> </div> + +<div class="box"> <marquee> +<?php system("uptime") ?> +</marquee> </div> + +<div class="box" id="planet"> +recent posts on the <a href="#">planet</a>: +<ul> +<li><a href="#">Lorem ipsum dorom</a> <span class="planetuser">~dzwdz</span></li> +<li><a href="#">Lorem ipsum dorom</a> <span class="planetuser">~dzwdz</span></li> +<li><a href="#">Lorem ipsum dorom</a> <span class="planetuser">~dzwdz</span></li> +<li><a href="#">Lorem ipsum dorom</a> <span class="planetuser">~dzwdz</span></li> +<li><a href="#">Lorem ipsum dorom</a> <span class="planetuser">~dzwdz</span></li> +</ul> +</div> + +<div class="box"> +<img src="//tilde.town/~lucidiot/img/logos/tildetown_anim2.gif" /> +<img src="//tilde.town/~juniperspring/gifs/adultchat.gif" /> +<img src="//tilde.town/~dzwdz/pics/88x31/firefox2.gif" /> +<img src="//tilde.town/~dzwdz/pics/88x31/transnow2.gif" /> +<img src="//tilde.town/~dzwdz/pics/88x31/ubuntu-88x31.gif" /> +<img src="//tilde.town/~dzwdz/pics/88x31/php4_88x31.gif" /> +</div> +</aside> + +<aside id="users"> +<!-- TODO choose only from townies who edited their site. --> +some random users: +<ul> +<?php system("shuf -n125 userbar.html") ?> +</ul> +</aside> diff --git a/lastlog.c b/lastlog.c new file mode 100644 index 0000000..9036527 --- /dev/null +++ b/lastlog.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1989 - 1994, Julianne Frances Haugh + * Copyright (c) 1996 - 2000, Marek Michałkiewicz + * Copyright (c) 2000 - 2006, Tomasz Kłoczko + * Copyright (c) 2007 - 2011, Nicolas François + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the copyright holders or contributors may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <assert.h> +#include <getopt.h> +#include <lastlog.h> +#include <pwd.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <time.h> +#include <stdbool.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <err.h> +#include <math.h> +#include <sys/param.h> + +/* + * Needed for MkLinux DR1/2/2.1 - J. + */ +#ifndef LASTLOG_FILE +#define LASTLOG_FILE "/var/log/lastlog" +#endif + +/* + * Global variables + */ +const char *Prog; /* Program name */ +static FILE *lastlogfile; /* lastlog file stream */ +static struct stat statbuf; /* fstat buffer for file size */ + +// TODO just put that in a variable... +#define NOW (time ((time_t *) 0)) + +static void print_one(const struct passwd *pw) +{ + char *cp; + struct tm *tm; + time_t ll_time; + off_t offset; + struct lastlog ll; + char ptime[80]; + + if (NULL == pw) { + return; + } + + offset = (off_t) pw->pw_uid * sizeof(ll); + if (offset + sizeof(ll) <= statbuf.st_size) { + /* fseeko errors are not really relevant for us. */ + int err = fseeko(lastlogfile, offset, SEEK_SET); + assert(0 == err); + /* lastlog is a sparse file. Even if no entries were + * entered for this user, which should be able to get the + * empty entry in this case. + */ + if (fread((char *) &ll, sizeof(ll), 1, lastlogfile) != 1) { + return; + } + } else { + /* Outsize of the lastlog file. + * Behave as if there were a missing entry (same behavior + * as if we were reading an non existing entry in the + * sparse lastlog file). + */ + memset(&ll, 0, sizeof(ll)); + } + + + ll_time = ll.ll_time; + tm = localtime(&ll_time); + strftime(ptime, sizeof(ptime), "%a %b %e %H:%M:%S %z %Y", tm); + cp = ptime; + + if (ll.ll_time == (time_t) 0) { + cp = "**Never logged in**\0"; + } + int ago = NOW-ll.ll_time; + float f = 1.0 - ((float)ago) / ((float)(60*60*24*365*5)); + if (f < 0.0) f = 0.0; + f = pow(f, 3.0); + float a = 80.0; + float b = 2.5; + f = MAX(f * f / b, f * a - a + 1.0); + float hue = f * 90.0 + 260.; + printf("<a href=\"/~%s\" title=\"%s\" style=\"background: hsl(%fdeg %f%% %f%%)\"></a>\n", pw->pw_name, pw->pw_name, hue, 20. + f*70., 10. + f*90.); +} + +int main(void) +{ + const struct passwd *pwent; + + lastlogfile = fopen(LASTLOG_FILE, "r"); + if (NULL == lastlogfile) { + perror(LASTLOG_FILE); + exit(EXIT_FAILURE); + } + + /* Get the lastlog size */ + if (fstat(fileno(lastlogfile), &statbuf) != 0) { + err(1, "can't get lastlog size"); + } + + setpwent(); + while ( (pwent = getpwent()) != NULL ) { + print_one(pwent); + } + endpwent(); + + (void) fclose(lastlogfile); + + return EXIT_SUCCESS; +} + diff --git a/userbar.sh b/userbar.sh new file mode 100755 index 0000000..606d5de --- /dev/null +++ b/userbar.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +for file in /home/*/public_html/index.html; do + cmp -s "$file" /etc/skel/public_html/index.html + if [ $? -eq 1 ]; then + user=${file##/home/} + user=${user%%/*} + printf '<li><a href="/~%s">~%s</a></li>\n' $user $user + fi +done |