If I created a Linux distribution
I’d keep it simple.
The 1st thing that I would change is the directory structure.
I’d have 1 directory called system
all OS stuff goes there
then I’d have a users dir
in the users dir I’d have
– programs dir
– data dir
– home dir
the programs dir would contain programs/applications
the home dir would contain data like pictures, video, music, documents
data would contain appdata, example firefox cache or ssh keys
/
/system/
/users/username/programs/firefox/
/users/username/data/firefox/
/users/username/home/pictures
/users/username/home/videos
/users/username/home/audio
/users/username/home/documents
/users/username/home/downloads
every program installed would run under its own user, exampe username.firefox
and group username
same with data, also username.firefox
home would be owned by username:username
and that’s it, now everything is orderly
next step: package management
create something as seen on MacOS. Essentially zip (or other) with metadata. fuse mount those archives so the content can be executed.
as for the UI, take inspiration from ChromeOS, imho that’s a clean and orderly UI.
programs that are running are automatically put on the bottom bar.
you can pin them for quick access. apart from that categorize, tag so they can easily be found and/or installed/removed.
Samba, anonymous access, which system user?
I searched around and found nothing so here it is:
TL;DR: the user and group is “nobody”
my smb.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
[Global] workgroup = LUKETIC security = user domain master = yes domain logons = yes local master = yes preferred master = yes passdb backend = tdbsam logon path = \\%L\Profiles\%U logon script = logon.bat add machine script = /usr/sbin/useradd -d /dev/null -g 200 -s /sbin/nologin -M %u [homes] comment = Home Directories browseable = yes writable = yes [printers] comment = All Printers path = /var/spool/samba printable = Yes print ok = Yes browseable = No [netlogon] comment = Network Logon Service path = /var/lib/samba/netlogon browseable = No writable = No [Profiles] path = /var/lib/samba/profiles create mask = 0755 directory mask = 0755 writable = Yes [Storage] path = /srv/Storage create mask = 0755 directory mask = 0755 writable = Yes guest ok = Yes guest only = Yes |
run
|
1 |
chown -R nobody:nobody /srv/Storage |
Flatrate ist kein Volumentarif
Liebe oder eher nicht so liebe Mobilfunkanbieter,
Wenn da 16Mbit/s FLATRATE steht und darunter 1GB Transfervolumen, dann ist das keine Flatrate sondern ein Volumentarif.
Wie klagt da eigentlich keiner? Sonst klagen doch auch alle wegen allem und ihrer Mutter
Using mgo and writing handlers in Go with net/http
This is a short example of how to write handlers in Go and use the MongoDB mgo driver.
Assume you want to write handlers that are in a package and mount this handler under a certain prefix,
for instance a HelloHandler mounted on /hello/.
So you have a main package and a handler package, called hello.
Directory structure is
~/go/src/example/hello/
~/go/src/example/hello/main.go
~/go/src/example/hello/hello/
~/go/src/example/hello/hello/hello.go
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package main import ( "example/hello/hello" "log" "net/http" "gopkg.in/mgo.v2" ) const ( // database name database = "hello" // collection name helloCollection = "messages" // mount point e.g. http://localhost:8080/hello/ helloMountpoint = "/hello/" ) func main() { // establish mongodb connection ms, e := mgo.Dial("localhost") if e != nil { log.Fatalln(e.Error()) } // create options using the convenience function ho := hello.NewHelloHandlerOptions(ms, database, helloCollection, helloMountpoint) // create handler using the convenience function hh := hello.NewHelloHandler(ho) // we need to close the mgo connection when the program exits defer hh.Close() // create new mux mux := http.NewServeMux() // and handle hello.HelloHandler on "/hello/" mux.Handle(helloMountpoint, http.StripPrefix(helloMountpoint, hh)) // log errors and exit on error, otherwise listen on :8080 log.Fatal(http.ListenAndServe(":8080", mux)) } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
package hello import ( "net/http" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) // our handler struct type HelloHandler struct { options *HelloHandlerOptions } // the handler's options that are passed type HelloHandlerOptions struct { ms *mgo.Session db string col string prefix string } // the mongodb message type/struct type Message struct { Id bson.ObjectId `bson:"_id,omitempty"` Name string `bson:",omitempty"` Text string } // create new hellohandler convenience function func NewHelloHandler(options *HelloHandlerOptions) *HelloHandler { return &HelloHandler{ options: options, } } // create new options convenience function func NewHelloHandlerOptions(ms *mgo.Session, db, col, prefix string) *HelloHandlerOptions { return &HelloHandlerOptions{ ms: ms.Clone(), db: db, col: col, prefix: prefix, } } // close the mgo connection func (h *HelloHandler) Close() { h.options.ms.Close() } // satify http.Handler interface func (h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": // display list of messages h.Get(w, r) case "POST": // process post request and create a new message if valid h.Post(w, r) default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) } } // I named it Get() you could also name it ListMessages() but also rename h.Get(w, r) to h.ListMessages(w, r) func (h *HelloHandler) Get(w http.ResponseWriter, r *http.Request) { // copy the session ms := h.options.ms.Copy() defer ms.Close() cMessage := ms.DB(h.options.db).C(h.options.col) // create holder for messages msgs := []*Message{} // query if e := cMessage.Find(nil).Sort("_id").All(&msgs); e != nil { http.Error(w, e.Error(), http.StatusInternalServerError) return } // create a template execution context ctx := make(map[string]interface{}) ctx["Messages"] = msgs // and render the template with context if e := tplHelloIndex.Execute(w, ctx); e != nil { // or return an error if there's an error in the template http.Error(w, e.Error(), http.StatusInternalServerError) } } func (h *HelloHandler) Post(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") message := r.FormValue("message") if message == "" { // since we're lazy return a http error http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } ms := h.options.ms.Copy() defer ms.Close() cMessage := ms.DB(h.options.db).C(h.options.col) // create the message msg := new(Message) msg.Id = bson.NewObjectId() msg.Name = name msg.Text = message // insert into database, if error return error if e := cMessage.Insert(msg); e != nil { http.Error(w, e.Error(), http.StatusInternalServerError) return } // else redirect back to display page http.Redirect(w, r, h.options.prefix, 302) } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package hello import ( "html/template" ) var tplHelloIndex = template.Must(template.New("index").Parse(helloIndexstring)) const helloIndexstring = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Hello</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> </head> <body> <div class="container"> <h1>Hello</h1> <h2>Leave a message</h2> <form method="post"> <div class="form-group"> <label for="name">Name</label> <input id="name" name="name" placeholder="Name" class="form-control"> </div> <div class="form-group"> <label for="message">Message</label> <textarea id="message" name="message" placeholder="Message" class="form-control" required></textarea> </div> <div class="form-group"> <button type="submit" class="btn btn-default btn-block">Submit</button> </div> </form> <h2>Messages</h2> {{ range .Messages }} <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">{{ .Name }} says</h3> </div> <div class="panel-body"> {{ .Text }} </div> <div class="panel-footer"> on {{ .Id.Time.Format "2 January at 3:04pm" }} </div> </div> {{ end }} </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> </body> </html> ` |
Run it
|
1 2 |
cd ~/go/src/example/hello go run main.go |
and navigate to http://localhost:8080/hello/
