17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "../port/error.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier static char Ebadlogctl[] = "unknown log ctl message";
97dd7cddfSDavid du Colombier
107dd7cddfSDavid du Colombier void
logopen(Log * alog)117dd7cddfSDavid du Colombier logopen(Log *alog)
127dd7cddfSDavid du Colombier {
137dd7cddfSDavid du Colombier lock(alog);
147dd7cddfSDavid du Colombier if(waserror()){
157dd7cddfSDavid du Colombier unlock(alog);
167dd7cddfSDavid du Colombier nexterror();
177dd7cddfSDavid du Colombier }
187dd7cddfSDavid du Colombier if(alog->opens == 0){
1980ee5cbfSDavid du Colombier if(alog->nlog == 0)
2080ee5cbfSDavid du Colombier alog->nlog = 4*1024;
2180ee5cbfSDavid du Colombier if(alog->minread == 0)
2280ee5cbfSDavid du Colombier alog->minread = 1;
23*5b0beceeSDavid du Colombier if(alog->buf == nil && (alog->buf = malloc(alog->nlog)) == nil)
24aa72973aSDavid du Colombier error(Enomem);
257dd7cddfSDavid du Colombier alog->rptr = alog->buf;
2680ee5cbfSDavid du Colombier alog->end = alog->buf + alog->nlog;
2780ee5cbfSDavid du Colombier alog->len = 0;
287dd7cddfSDavid du Colombier }
297dd7cddfSDavid du Colombier alog->opens++;
307dd7cddfSDavid du Colombier unlock(alog);
317dd7cddfSDavid du Colombier poperror();
327dd7cddfSDavid du Colombier }
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier void
logclose(Log * alog)357dd7cddfSDavid du Colombier logclose(Log *alog)
367dd7cddfSDavid du Colombier {
377dd7cddfSDavid du Colombier lock(alog);
387dd7cddfSDavid du Colombier alog->opens--;
397dd7cddfSDavid du Colombier if(alog->opens == 0){
407dd7cddfSDavid du Colombier free(alog->buf);
417dd7cddfSDavid du Colombier alog->buf = nil;
427dd7cddfSDavid du Colombier }
437dd7cddfSDavid du Colombier unlock(alog);
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier static int
logready(void * a)477dd7cddfSDavid du Colombier logready(void *a)
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier Log *alog = a;
507dd7cddfSDavid du Colombier
5180ee5cbfSDavid du Colombier return alog->len >= alog->minread;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier long
logread(Log * alog,void * a,ulong,long n)557dd7cddfSDavid du Colombier logread(Log *alog, void *a, ulong, long n)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier int i, d;
587dd7cddfSDavid du Colombier char *p, *rptr;
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier qlock(&alog->readq);
617dd7cddfSDavid du Colombier if(waserror()){
627dd7cddfSDavid du Colombier qunlock(&alog->readq);
637dd7cddfSDavid du Colombier nexterror();
647dd7cddfSDavid du Colombier }
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier for(;;){
677dd7cddfSDavid du Colombier lock(alog);
6880ee5cbfSDavid du Colombier if(alog->len >= alog->minread || alog->len >= n){
697dd7cddfSDavid du Colombier if(n > alog->len)
707dd7cddfSDavid du Colombier n = alog->len;
717dd7cddfSDavid du Colombier d = 0;
727dd7cddfSDavid du Colombier rptr = alog->rptr;
737dd7cddfSDavid du Colombier alog->rptr += n;
747dd7cddfSDavid du Colombier if(alog->rptr >= alog->end){
757dd7cddfSDavid du Colombier d = alog->rptr - alog->end;
767dd7cddfSDavid du Colombier alog->rptr = alog->buf + d;
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier alog->len -= n;
797dd7cddfSDavid du Colombier unlock(alog);
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier i = n-d;
827dd7cddfSDavid du Colombier p = a;
837dd7cddfSDavid du Colombier memmove(p, rptr, i);
847dd7cddfSDavid du Colombier memmove(p+i, alog->buf, d);
857dd7cddfSDavid du Colombier break;
867dd7cddfSDavid du Colombier }
877dd7cddfSDavid du Colombier else
887dd7cddfSDavid du Colombier unlock(alog);
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier sleep(&alog->readr, logready, alog);
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier qunlock(&alog->readq);
947dd7cddfSDavid du Colombier poperror();
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier return n;
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier char*
logctl(Log * alog,int argc,char * argv[],Logflag * flags)1007dd7cddfSDavid du Colombier logctl(Log *alog, int argc, char *argv[], Logflag *flags)
1017dd7cddfSDavid du Colombier {
1027dd7cddfSDavid du Colombier int i, set;
1037dd7cddfSDavid du Colombier Logflag *fp;
1047dd7cddfSDavid du Colombier
1057dd7cddfSDavid du Colombier if(argc < 2)
1067dd7cddfSDavid du Colombier return Ebadlogctl;
1077dd7cddfSDavid du Colombier
1087dd7cddfSDavid du Colombier if(strcmp("set", argv[0]) == 0)
1097dd7cddfSDavid du Colombier set = 1;
1107dd7cddfSDavid du Colombier else if(strcmp("clear", argv[0]) == 0)
1117dd7cddfSDavid du Colombier set = 0;
1127dd7cddfSDavid du Colombier else
1137dd7cddfSDavid du Colombier return Ebadlogctl;
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier for(i = 1; i < argc; i++){
1167dd7cddfSDavid du Colombier for(fp = flags; fp->name; fp++)
1177dd7cddfSDavid du Colombier if(strcmp(fp->name, argv[i]) == 0)
1187dd7cddfSDavid du Colombier break;
1197dd7cddfSDavid du Colombier if(fp->name == nil)
1207dd7cddfSDavid du Colombier continue;
1217dd7cddfSDavid du Colombier if(set)
1227dd7cddfSDavid du Colombier alog->logmask |= fp->mask;
1237dd7cddfSDavid du Colombier else
1247dd7cddfSDavid du Colombier alog->logmask &= ~fp->mask;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier return nil;
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier
1307dd7cddfSDavid du Colombier void
logn(Log * alog,int mask,void * buf,int n)13180ee5cbfSDavid du Colombier logn(Log *alog, int mask, void *buf, int n)
1327dd7cddfSDavid du Colombier {
13380ee5cbfSDavid du Colombier char *fp, *t;
13480ee5cbfSDavid du Colombier int dowake, i;
1357dd7cddfSDavid du Colombier
1367dd7cddfSDavid du Colombier if(!(alog->logmask & mask))
1377dd7cddfSDavid du Colombier return;
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier if(alog->opens == 0)
1407dd7cddfSDavid du Colombier return;
1417dd7cddfSDavid du Colombier
14280ee5cbfSDavid du Colombier if(n > alog->nlog)
14380ee5cbfSDavid du Colombier return;
14480ee5cbfSDavid du Colombier
1457dd7cddfSDavid du Colombier lock(alog);
14680ee5cbfSDavid du Colombier i = alog->len + n - alog->nlog;
1477dd7cddfSDavid du Colombier if(i > 0){
1487dd7cddfSDavid du Colombier alog->len -= i;
1497dd7cddfSDavid du Colombier alog->rptr += i;
1507dd7cddfSDavid du Colombier if(alog->rptr >= alog->end)
1517dd7cddfSDavid du Colombier alog->rptr = alog->buf + (alog->rptr - alog->end);
1527dd7cddfSDavid du Colombier }
1537dd7cddfSDavid du Colombier t = alog->rptr + alog->len;
1547dd7cddfSDavid du Colombier fp = buf;
1557dd7cddfSDavid du Colombier alog->len += n;
1567dd7cddfSDavid du Colombier while(n-- > 0){
1577dd7cddfSDavid du Colombier if(t >= alog->end)
1587dd7cddfSDavid du Colombier t = alog->buf + (t - alog->end);
1597dd7cddfSDavid du Colombier *t++ = *fp++;
1607dd7cddfSDavid du Colombier }
16180ee5cbfSDavid du Colombier dowake = alog->len >= alog->minread;
1627dd7cddfSDavid du Colombier unlock(alog);
1637dd7cddfSDavid du Colombier
16480ee5cbfSDavid du Colombier if(dowake)
1657dd7cddfSDavid du Colombier wakeup(&alog->readr);
1667dd7cddfSDavid du Colombier }
16780ee5cbfSDavid du Colombier
16880ee5cbfSDavid du Colombier void
log(Log * alog,int mask,char * fmt,...)1699a747e4fSDavid du Colombier log(Log *alog, int mask, char *fmt, ...)
17080ee5cbfSDavid du Colombier {
17180ee5cbfSDavid du Colombier int n;
1729a747e4fSDavid du Colombier va_list arg;
1739a747e4fSDavid du Colombier char buf[128];
17480ee5cbfSDavid du Colombier
17580ee5cbfSDavid du Colombier if(!(alog->logmask & mask))
17680ee5cbfSDavid du Colombier return;
17780ee5cbfSDavid du Colombier
17880ee5cbfSDavid du Colombier if(alog->opens == 0)
17980ee5cbfSDavid du Colombier return;
18080ee5cbfSDavid du Colombier
1819a747e4fSDavid du Colombier va_start(arg, fmt);
1829a747e4fSDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
1839a747e4fSDavid du Colombier va_end(arg);
18480ee5cbfSDavid du Colombier
18580ee5cbfSDavid du Colombier logn(alog, mask, buf, n);
18680ee5cbfSDavid du Colombier }
187