1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 8 static char Ebadlogctl[] = "unknown log ctl message"; 9 10 void 11 logopen(Log *alog) 12 { 13 lock(alog); 14 if(waserror()){ 15 unlock(alog); 16 nexterror(); 17 } 18 if(alog->opens == 0){ 19 if(alog->nlog == 0) 20 alog->nlog = 4*1024; 21 if(alog->minread == 0) 22 alog->minread = 1; 23 if(alog->buf == nil) 24 alog->buf = malloc(alog->nlog); 25 alog->rptr = alog->buf; 26 alog->end = alog->buf + alog->nlog; 27 alog->len = 0; 28 } 29 alog->opens++; 30 unlock(alog); 31 poperror(); 32 } 33 34 void 35 logclose(Log *alog) 36 { 37 lock(alog); 38 alog->opens--; 39 if(alog->opens == 0){ 40 free(alog->buf); 41 alog->buf = nil; 42 } 43 unlock(alog); 44 } 45 46 static int 47 logready(void *a) 48 { 49 Log *alog = a; 50 51 return alog->len >= alog->minread; 52 } 53 54 long 55 logread(Log *alog, void *a, ulong, long n) 56 { 57 int i, d; 58 char *p, *rptr; 59 60 qlock(&alog->readq); 61 if(waserror()){ 62 qunlock(&alog->readq); 63 nexterror(); 64 } 65 66 for(;;){ 67 lock(alog); 68 if(alog->len >= alog->minread || alog->len >= n){ 69 if(n > alog->len) 70 n = alog->len; 71 d = 0; 72 rptr = alog->rptr; 73 alog->rptr += n; 74 if(alog->rptr >= alog->end){ 75 d = alog->rptr - alog->end; 76 alog->rptr = alog->buf + d; 77 } 78 alog->len -= n; 79 unlock(alog); 80 81 i = n-d; 82 p = a; 83 memmove(p, rptr, i); 84 memmove(p+i, alog->buf, d); 85 break; 86 } 87 else 88 unlock(alog); 89 90 sleep(&alog->readr, logready, alog); 91 } 92 93 qunlock(&alog->readq); 94 poperror(); 95 96 return n; 97 } 98 99 char* 100 logctl(Log *alog, int argc, char *argv[], Logflag *flags) 101 { 102 int i, set; 103 Logflag *fp; 104 105 if(argc < 2) 106 return Ebadlogctl; 107 108 if(strcmp("set", argv[0]) == 0) 109 set = 1; 110 else if(strcmp("clear", argv[0]) == 0) 111 set = 0; 112 else 113 return Ebadlogctl; 114 115 for(i = 1; i < argc; i++){ 116 for(fp = flags; fp->name; fp++) 117 if(strcmp(fp->name, argv[i]) == 0) 118 break; 119 if(fp->name == nil) 120 continue; 121 if(set) 122 alog->logmask |= fp->mask; 123 else 124 alog->logmask &= ~fp->mask; 125 } 126 127 return nil; 128 } 129 130 void 131 logn(Log *alog, int mask, void *buf, int n) 132 { 133 char *fp, *t; 134 int dowake, i; 135 136 if(!(alog->logmask & mask)) 137 return; 138 139 if(alog->opens == 0) 140 return; 141 142 if(n > alog->nlog) 143 return; 144 145 lock(alog); 146 i = alog->len + n - alog->nlog; 147 if(i > 0){ 148 alog->len -= i; 149 alog->rptr += i; 150 if(alog->rptr >= alog->end) 151 alog->rptr = alog->buf + (alog->rptr - alog->end); 152 } 153 t = alog->rptr + alog->len; 154 fp = buf; 155 alog->len += n; 156 while(n-- > 0){ 157 if(t >= alog->end) 158 t = alog->buf + (t - alog->end); 159 *t++ = *fp++; 160 } 161 dowake = alog->len >= alog->minread; 162 unlock(alog); 163 164 if(dowake) 165 wakeup(&alog->readr); 166 } 167 168 void 169 logb(Log *alog, int mask, char *fmt, ...) 170 { 171 int n; 172 va_list arg; 173 char buf[128]; 174 175 if(!(alog->logmask & mask)) 176 return; 177 178 if(alog->opens == 0) 179 return; 180 181 va_start(arg, fmt); 182 n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; 183 va_end(arg); 184 185 logn(alog, mask, buf, n); 186 } 187