all repos — honk @ 24ca3b753ef34752f2549e4528ffc067a17a4dcc

my fork of honk

main.go (view raw)

  1//
  2// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
  3//
  4// Permission to use, copy, modify, and distribute this software for any
  5// purpose with or without fee is hereby granted, provided that the above
  6// copyright notice and this permission notice appear in all copies.
  7//
  8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15
 16package main
 17
 18import (
 19	"flag"
 20	"fmt"
 21	"html/template"
 22	golog "log"
 23	"log/syslog"
 24	notrand "math/rand"
 25	"os"
 26	"runtime/pprof"
 27	"sort"
 28	"strings"
 29	"time"
 30
 31	"humungus.tedunangst.com/r/webs/log"
 32)
 33
 34var softwareVersion = "develop"
 35
 36func init() {
 37	notrand.Seed(time.Now().Unix())
 38}
 39
 40var serverName string
 41var serverPrefix string
 42var masqName string
 43var dataDir = "."
 44var viewDir = "."
 45var iconName = "icon.png"
 46var serverMsg template.HTML
 47var aboutMsg template.HTML
 48var loginMsg template.HTML
 49
 50func serverURL(u string, args ...interface{}) string {
 51	return fmt.Sprintf("https://"+serverName+u, args...)
 52}
 53
 54func ElaborateUnitTests() {
 55	user, _ := butwhatabout("test")
 56	syndicate(user, "https://mastodon.social/tags/mastoadmin.rss")
 57}
 58
 59func unplugserver(hostname string) {
 60	db := opendatabase()
 61	xid := fmt.Sprintf("https://%s", hostname)
 62	db.Exec("delete from honkers where xid = ? and flavor = 'dub'", xid)
 63	db.Exec("delete from doovers where rcpt = ?", xid)
 64	xid += "/%"
 65	db.Exec("delete from honkers where xid like ? and flavor = 'dub'", xid)
 66	db.Exec("delete from doovers where rcpt like ?", xid)
 67}
 68
 69func reexecArgs(cmd string) []string {
 70	args := []string{"-datadir", dataDir}
 71	args = append(args, log.Args()...)
 72	args = append(args, cmd)
 73	return args
 74}
 75
 76var elog, ilog, dlog *golog.Logger
 77
 78func errx(msg string, args ...interface{}) {
 79	fmt.Fprintf(os.Stderr, msg+"\n", args...)
 80	os.Exit(1)
 81}
 82
 83var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
 84var memprofile = flag.String("memprofile", "", "write memory profile to this file")
 85var memprofilefd *os.File
 86
 87func usage() {
 88	flag.PrintDefaults()
 89	out := flag.CommandLine.Output()
 90	fmt.Fprintf(out, "\n  available honk commands:\n")
 91	var msgs []string
 92	for n, c := range commands {
 93		msgs = append(msgs, fmt.Sprintf("    %s: %s\n", n, c.help))
 94	}
 95	sort.Strings(msgs)
 96	fmt.Fprintf(out, "%s", strings.Join(msgs, ""))
 97}
 98
 99func main() {
100	commands["help"] = cmd{
101		help: "you're looking at it",
102		callback: func(args []string) {
103			usage()
104		},
105	}
106	flag.StringVar(&dataDir, "datadir", getenv("HONK_DATADIR", dataDir), "data directory")
107	flag.StringVar(&viewDir, "viewdir", getenv("HONK_VIEWDIR", viewDir), "view directory")
108	flag.Usage = usage
109
110	flag.Parse()
111	if *cpuprofile != "" {
112		f, err := os.Create(*cpuprofile)
113		if err != nil {
114			errx("can't open cpu profile: %s", err)
115		}
116		pprof.StartCPUProfile(f)
117	}
118	if *memprofile != "" {
119		f, err := os.Create(*memprofile)
120		if err != nil {
121			errx("can't open mem profile: %s", err)
122		}
123		memprofilefd = f
124	}
125
126	log.Init(log.Options{Progname: "honk", Facility: syslog.LOG_UUCP})
127	elog = log.E
128	ilog = log.I
129	dlog = log.D
130
131	if os.Geteuid() == 0 {
132		elog.Fatalf("do not run honk as root")
133	}
134
135	args := flag.Args()
136	cmd := "run"
137	if len(args) > 0 {
138		cmd = args[0]
139	}
140	switch cmd {
141	case "init":
142		commands["init"].callback(args)
143	case "upgrade":
144		commands["upgrade"].callback(args)
145	case "version":
146		commands["version"].callback(args)
147	}
148	db := opendatabase()
149	dbversion := 0
150	getconfig("dbversion", &dbversion)
151	if dbversion != myVersion {
152		elog.Fatal("incorrect database version. run upgrade.")
153	}
154	getconfig("servermsg", &serverMsg)
155	getconfig("aboutmsg", &aboutMsg)
156	getconfig("loginmsg", &loginMsg)
157	getconfig("servername", &serverName)
158	getconfig("masqname", &masqName)
159	if masqName == "" {
160		masqName = serverName
161	}
162	serverPrefix = serverURL("/")
163	getconfig("usersep", &userSep)
164	getconfig("honksep", &honkSep)
165	getconfig("devel", &develMode)
166	if develMode {
167		gogglesDoNothing()
168	}
169	getconfig("fasttimeout", &fastTimeout)
170	getconfig("slowtimeout", &slowTimeout)
171	getconfig("honkwindow", &honkwindow)
172	honkwindow *= 24 * time.Hour
173
174	prepareStatements(db)
175
176	dbx := opendatabasex()
177	prepareStatementsx(dbx)
178
179	c, ok := commands[cmd]
180	if !ok {
181		errx("don't know about %q", cmd)
182	}
183
184	c.callback(args)
185}