func listen() net.Listener { socket := google.Dir() + "/socket" os.Remove(socket) l, err := net.Listen("unix", socket) if err != nil { log.Fatal(err) } return l }
func serve() { f, err := os.OpenFile(google.Dir()+"/log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) if err != nil { log.Fatal(err) } log.SetOutput(f) syscall.Dup2(f.Fd(), 2) os.Stdout = f os.Stderr = f l := listen() rpc.RegisterName("goog", &Server{}) rpc.Accept(l) log.Fatal("rpc.Accept finished: server exiting") }
func main() { flag.Usage = usage flag.Parse() acct = google.Acct(*acctName) aw, err := acme.New() if err != nil { log.Fatal(err) } aw.Name("Chat/" + acct.Nick + "/") client, err = xmpp.NewClient("talk.google.com:443", acct.Email, acct.Password) if err != nil { log.Fatal(err) } w := &Window{Win: aw, typ: "main", name: "Chat/" + acct.Nick + "/"} data, err := ioutil.ReadFile(google.Dir() + "/chat." + acct.Nick) if err != nil { log.Fatal(err) } if err == nil { w.Write("body", data) } mainWin = w active[w.name] = w go w.readAcme() client.Roster() setStatus(status) go w.readChat() lastActivity = time.Now() tick := time.Tick(0.5e9) Loop: for len(active) > 0 { select { case w := <-acmeChan: if w == nil { // Sync with reader. continue } if w.err != nil { if active[w.name] == nil { continue } log.Fatal(w.err) } if *acmeDebug { fmt.Fprintf(os.Stderr, "%s %c%c %d,%d %q\n", w.name, w.C1, w.C2, w.Q0, w.Q1, w.Text) } if w.C1 == 'M' || w.C1 == 'K' { lastActivity = time.Now() if status != xmpp.Available { setStatus(xmpp.Available) } } if (w.C2 == 'x' || w.C2 == 'X') && string(w.Text) == "Del" { // TODO: Hangup connection for w.typ == "acct"? delete(active, w.name) w.Del(true) continue Loop } switch w.typ { case "main": switch w.C2 { case 'L': // Button 3 in body: load chat window for contact. w.expand() fallthrough case 'l': // Button 3 in tag arg := string(w.Text) showContact(arg) continue Loop } case "chat": if w.C1 == 'F' && w.C2 == 'I' { continue Loop } if w.C1 != 'M' && w.C1 != 'K' { break } if w.blinky { w.blinky = false w.Fprintf("ctl", "dirty\n") } switch w.C2 { case 'X', 'x': if string(w.Text) == "Ack" { w.Fprintf("ctl", "clean\n") } case 'I': w.sendMsg() continue Loop } } w.WriteEvent(w.Event) case msg := <-msgChan: w := msg.w if msg.err != nil { w.Fprintf("body", "ERROR: %s\n", msg.err) continue Loop } you := msg.Remote if i := strings.Index(you, "/"); i >= 0 { you = you[:i] } switch msg.Type { case "chat": w := showContact(you) text := strings.TrimSpace(msg.Text) if text == "" { // Probably a composing notification. continue } w.message("> %s\n", text) w.blinky = true w.dirty = true case "presence": pr := msg.Presence pr, new := savePresence(pr, you) if !new { continue } w := lookContact(you) if w != nil { w.status(pr) } mainStatus(pr, you) } case t := <-tick: switch status { case xmpp.Available: if t.Sub(lastActivity) > awayTime { setStatus(xmpp.Away) } case xmpp.Away: if t.Sub(lastActivity) > extendedAwayTime { setStatus(xmpp.ExtendedAway) } } for _, w := range active { if w.blinky { w.dirty = !w.dirty if w.dirty { w.Fprintf("ctl", "dirty\n") } else { w.Fprintf("ctl", "clean\n") } } } } } }