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 "time"
28
29 "humungus.tedunangst.com/r/webs/log"
30)
31
32var softwareVersion = "develop"
33
34func init() {
35 notrand.Seed(time.Now().Unix())
36}
37
38var serverName string
39var serverPrefix string
40var masqName string
41var dataDir = "."
42var viewDir = "."
43var iconName = "icon.png"
44var serverMsg template.HTML
45var aboutMsg template.HTML
46var loginMsg template.HTML
47
48func serverURL(u string, args ...interface{}) string {
49 return fmt.Sprintf("https://"+serverName+u, args...)
50}
51
52func ElaborateUnitTests() {
53 user, _ := butwhatabout("test")
54 syndicate(user, "https://mastodon.social/tags/mastoadmin.rss")
55}
56
57func unplugserver(hostname string) {
58 db := opendatabase()
59 xid := fmt.Sprintf("https://%s", hostname)
60 db.Exec("delete from honkers where xid = ? and flavor = 'dub'", xid)
61 db.Exec("delete from doovers where rcpt = ?", xid)
62 xid += "/%"
63 db.Exec("delete from honkers where xid like ? and flavor = 'dub'", xid)
64 db.Exec("delete from doovers where rcpt like ?", xid)
65}
66
67func reexecArgs(cmd string) []string {
68 args := []string{"-datadir", dataDir}
69 args = append(args, log.Args()...)
70 args = append(args, cmd)
71 return args
72}
73
74var elog, ilog, dlog *golog.Logger
75
76func errx(msg string, args ...interface{}) {
77 fmt.Fprintf(os.Stderr, msg+"\n", args...)
78 os.Exit(1)
79}
80
81var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
82var memprofile = flag.String("memprofile", "", "write memory profile to this file")
83var memprofilefd *os.File
84
85func main() {
86 flag.StringVar(&dataDir, "datadir", dataDir, "data directory")
87 flag.StringVar(&viewDir, "viewdir", viewDir, "view directory")
88 flag.Usage = func() {
89 flag.PrintDefaults()
90 helpText := "\n available honk commands:\n"
91 for n, c := range commands {
92 helpText += fmt.Sprintf(" %s: %s\n", n, c.help)
93 }
94
95 fmt.Fprint(flag.CommandLine.Output(), helpText)
96 }
97
98 flag.Parse()
99 if *cpuprofile != "" {
100 f, err := os.Create(*cpuprofile)
101 if err != nil {
102 errx("can't open cpu profile: %s", err)
103 }
104 pprof.StartCPUProfile(f)
105 }
106 if *memprofile != "" {
107 f, err := os.Create(*memprofile)
108 if err != nil {
109 errx("can't open mem profile: %s", err)
110 }
111 memprofilefd = f
112 }
113
114 log.Init(log.Options{Progname: "honk", Facility: syslog.LOG_UUCP})
115 elog = log.E
116 ilog = log.I
117 dlog = log.D
118
119 if os.Geteuid() == 0 {
120 elog.Fatalf("do not run honk as root")
121 }
122
123 args := flag.Args()
124 cmd := "run"
125 if len(args) > 0 {
126 cmd = args[0]
127 }
128 switch cmd {
129 case "init":
130 commands["init"].callback(args)
131 case "upgrade":
132 commands["upgrade"].callback(args)
133 case "version":
134 commands["version"].callback(args)
135 }
136 db := opendatabase()
137 dbversion := 0
138 getconfig("dbversion", &dbversion)
139 if dbversion != myVersion {
140 elog.Fatal("incorrect database version. run upgrade.")
141 }
142 getconfig("servermsg", &serverMsg)
143 getconfig("aboutmsg", &aboutMsg)
144 getconfig("loginmsg", &loginMsg)
145 getconfig("servername", &serverName)
146 getconfig("masqname", &masqName)
147 if masqName == "" {
148 masqName = serverName
149 }
150 serverPrefix = serverURL("/")
151 getconfig("usersep", &userSep)
152 getconfig("honksep", &honkSep)
153 getconfig("devel", &develMode)
154 if develMode {
155 gogglesDoNothing()
156 }
157 getconfig("fasttimeout", &fastTimeout)
158 getconfig("slowtimeout", &slowTimeout)
159 getconfig("honkwindow", &honkwindow)
160 honkwindow *= 24 * time.Hour
161
162 prepareStatements(db)
163
164 c, ok := commands[cmd]
165 if !ok {
166 errx("don't know about %q", cmd)
167 }
168
169 c.callback(args)
170}