1 #include "a.h"
2 
3 void
lbkick(Logbuf * lb)4 lbkick(Logbuf *lb)
5 {
6 	char *s;
7 	int n;
8 	Req *r;
9 
10 	while(lb->wait && lb->rp != lb->wp){
11 		r = lb->wait;
12 		lb->wait = r->aux;
13 		if(lb->wait == nil)
14 			lb->waitlast = &lb->wait;
15 		r->aux = nil;
16 		if(r->ifcall.count < 5){
17 			respond(r, "log read request count too short");
18 			continue;
19 		}
20 		s = lb->msg[lb->rp];
21 		lb->msg[lb->rp] = nil;
22 		if(++lb->rp == nelem(lb->msg))
23 			lb->rp = 0;
24 		n = r->ifcall.count;
25 		if(n < strlen(s)+1+1){
26 			memmove(r->ofcall.data, s, n-5);
27 			n -= 5;
28 			r->ofcall.data[n] = '\0';
29 			/* look for first byte of UTF-8 sequence by skipping continuation bytes */
30 			while(n>0 && (r->ofcall.data[--n]&0xC0)==0x80)
31 				;
32 			strcpy(r->ofcall.data+n, "...\n");
33 		}else{
34 			strcpy(r->ofcall.data, s);
35 			strcat(r->ofcall.data, "\n");
36 		}
37 		r->ofcall.count = strlen(r->ofcall.data);
38 		free(s);
39 		respond(r, nil);
40 	}
41 }
42 
43 void
lbread(Logbuf * lb,Req * r)44 lbread(Logbuf *lb, Req *r)
45 {
46 	if(lb->waitlast == nil)
47 		lb->waitlast = &lb->wait;
48 	*lb->waitlast = r;
49 	lb->waitlast = (Req**)(void*)&r->aux;
50 	r->aux = nil;
51 	lbkick(lb);
52 }
53 
54 void
lbflush(Logbuf * lb,Req * r)55 lbflush(Logbuf *lb, Req *r)
56 {
57 	Req **l;
58 
59 	for(l=&lb->wait; *l; l=(Req**)(void*)&(*l)->aux){
60 		if(*l == r){
61 			*l = r->aux;
62 			r->aux = nil;
63 			if(*l == nil)
64 				lb->waitlast = l;
65 			respond(r, "interrupted");
66 			break;
67 		}
68 	}
69 }
70 
71 void
lbappend(Logbuf * lb,char * fmt,...)72 lbappend(Logbuf *lb, char *fmt, ...)
73 {
74 	va_list arg;
75 
76 	va_start(arg, fmt);
77 	lbvappend(lb, fmt, arg);
78 	va_end(arg);
79 }
80 
81 void
lbvappend(Logbuf * lb,char * fmt,va_list arg)82 lbvappend(Logbuf *lb, char *fmt, va_list arg)
83 {
84 	char *s;
85 
86 	s = vsmprint(fmt, arg);
87 	if(s == nil)
88 		sysfatal("out of memory");
89 	if(lb->msg[lb->wp])
90 		free(lb->msg[lb->wp]);
91 	lb->msg[lb->wp] = s;
92 	if(++lb->wp == nelem(lb->msg))
93 		lb->wp = 0;
94 	lbkick(lb);
95 }
96 
97 Logbuf rpclogbuf;
98 
99 void
rpclogread(Req * r)100 rpclogread(Req *r)
101 {
102 	lbread(&rpclogbuf, r);
103 }
104 
105 void
rpclogflush(Req * r)106 rpclogflush(Req *r)
107 {
108 	lbflush(&rpclogbuf, r);
109 }
110 
111 void
rpclog(char * fmt,...)112 rpclog(char *fmt, ...)
113 {
114 	va_list arg;
115 
116 	va_start(arg, fmt);
117 	lbvappend(&rpclogbuf, fmt, arg);
118 	va_end(arg);
119 }
120