Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/coshell/misc.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Bell Laboratories
24
*
25
* remote coshell server miscellaneous support
26
*/
27
28
#include "service.h"
29
30
#include <hashkey.h>
31
32
#define STATS(a,b) do{STAT1(a);STAT1(b);}while(0)
33
#define STAT1(p) do{if((p)->update<=cs.time+UPDATE)update(p);}while(0)
34
35
typedef struct
36
{
37
char* data;
38
int size;
39
} String_t;
40
41
/*
42
* create a remote service connect stream
43
* malloc'd stream pathname is returned
44
*/
45
46
char*
47
stream(int type, register char* name)
48
{
49
register int fd;
50
register char* path;
51
52
if ((fd = csopen("/dev/tcp/local/normal", CS_OPEN_CREATE)) < 0)
53
error(ERROR_SYSTEM|3, "%s: cannot create connect stream", name);
54
if (!(path = strdup(cspath(fd, 0))))
55
error(3, "out of space [%s]", name);
56
state.con[fd].type = type;
57
csfd(fd, CS_POLL_READ);
58
message((-1, "%s connect stream path is %s", name, path));
59
return(path);
60
}
61
62
/*
63
* copy string v length n into s max length m
64
* v==0 || v=="-" converted to "*"
65
*/
66
67
static void
68
copystring(char* s, int m, const char* v, int n)
69
{
70
if (n <= 0) n = strlen(v);
71
if (n <= 0 || n == 1 && *v == '-')
72
{
73
n = 1;
74
s[0] = '*';
75
}
76
else
77
{
78
if (n >= m) n = m - 1;
79
memcpy(s, v, n);
80
}
81
s[n] = 0;
82
}
83
84
/*
85
* save string s length n into p
86
* v==0 || v=="-" converted to 0
87
*/
88
89
static char*
90
savestring(String_t* p, const char* v, int n)
91
{
92
if (n <= 0 || n == 1 && *v == '-')
93
return(0);
94
if (n >= p->size)
95
{
96
p->size = roundof(n + 1, 32);
97
if (!(p->data = newof(p->data, char, p->size, 0)))
98
error(3, "out of space [savestring]");
99
}
100
memcpy(p->data, v, n);
101
p->data[n] = 0;
102
return(p->data);
103
}
104
105
#define LT (1<<0)
106
#define EQ (1<<1)
107
#define GT (1<<2)
108
#define NOT (1<<3)
109
110
#define NE (NOT|EQ)
111
#define LE (LT|EQ)
112
#define GE (GT|EQ)
113
114
/*
115
* evaluate n1 op n2
116
*/
117
118
static int
119
miscop(unsigned long n1, int op, unsigned long n2)
120
{
121
switch (op)
122
{
123
case EQ:
124
return(n1 == n2);
125
case NE:
126
return(n1 != n2);
127
case LT:
128
return(n1 < n2);
129
case LE:
130
return(n1 <= n2);
131
case GE:
132
return(n1 >= n2);
133
case GT:
134
return(n1 > n2);
135
}
136
return(0);
137
}
138
139
/*
140
* compare the string value vp with the string (sb,se-1)
141
*/
142
143
static int
144
misccmp(char* vp, int op, char* sb, char* se)
145
{
146
int c;
147
int r;
148
149
c = *se;
150
*se = 0;
151
switch (op)
152
{
153
case EQ:
154
case NE:
155
r = (strmatch(vp, sb) || strchr(vp, '|') && strmatch(sb, vp)) == (op == EQ);
156
break;
157
case LT:
158
r = strcoll(vp, sb) < 0;
159
break;
160
case LE:
161
r = strcoll(vp, sb) <= 0;
162
break;
163
case GE:
164
r = strcoll(vp, sb) >= 0;
165
break;
166
case GT:
167
r = strcoll(vp, sb) > 0;
168
break;
169
default:
170
r = 0;
171
break;
172
}
173
*se = c;
174
return(r);
175
}
176
177
/*
178
* return attribute value for s in sp
179
* if set!=0 then non-zero returned if s is set in sp and e points to
180
* the matched attribute in sp
181
* otherwise value is returned and e is set to point to after the
182
* end of the attribute id in s
183
* if set!=0 && rep!=0 then replace value in sp with s up to rep
184
*/
185
186
static long
187
miscget(Coshell_t* sp, const char* as, int set, char** e, char* rep)
188
{
189
register char* s = (char*)as;
190
register char* cp;
191
register char* np;
192
register int c;
193
unsigned long x;
194
int no;
195
int op;
196
char* bp;
197
char* sb;
198
char* se;
199
char* st;
200
char* ee;
201
Coshell_t* osp;
202
Coshell_t* tsp;
203
204
if (s && (isalpha(*s) || *s == '_'))
205
{
206
if (no = *s == 'n' && *(s + 1) == 'o' && (isalnum(*(s + 2)) || *(s + 2) == '_')) s += 2;
207
osp = 0;
208
bp = s;
209
x = 0;
210
sb = bp + HASHKEYMAX;
211
while (isalnum(c = *s++) || c == '_')
212
if (s <= sb)
213
x = HASHKEYPART(x, c);
214
s--;
215
sb = 0;
216
if (!set)
217
{
218
for (cp = s; isspace(*cp); cp++);
219
if (*cp == '@')
220
{
221
osp = sp;
222
while (isspace(*++cp));
223
se = cp;
224
while (isalnum(*cp) || *cp == '_') cp++;
225
*e = cp;
226
c = *cp;
227
*cp = 0;
228
sp = search(GET, se, NiL, NiL);
229
*cp = c;
230
if (!sp) return(0);
231
while (isspace(*cp)) cp++;
232
*e = cp;
233
}
234
else *e = (char*)s;
235
switch (*cp)
236
{
237
case '<':
238
op = LT;
239
break;
240
case '>':
241
op = GT;
242
break;
243
case '=':
244
op = EQ;
245
break;
246
case '!':
247
op = NOT;
248
break;
249
default:
250
op = 0;
251
break;
252
}
253
if (op)
254
{
255
if (*++cp == '=')
256
{
257
cp++;
258
op |= EQ;
259
}
260
while (isspace(*cp)) cp++;
261
if ((c = *cp) == '"' || c == '\'')
262
{
263
sb = ++cp;
264
while (*cp && *cp != c) cp++;
265
if (*(se = cp)) cp++;
266
ee = cp;
267
}
268
else if (isalpha(*cp) || *cp == '_')
269
{
270
se = cp;
271
while (isalnum(*++se));
272
st = se;
273
while (isspace(*se)) se++;
274
if (*se == '@')
275
{
276
sb = cp;
277
while (isspace(*++se));
278
cp = se;
279
while (isalnum(*cp) || *cp == '_') cp++;
280
c = *cp;
281
*cp = 0;
282
tsp = search(GET, se, NiL, NiL);
283
*cp = c;
284
ee = cp;
285
if (tsp)
286
{
287
c = *st;
288
*st = 0;
289
if ((st - sb) == 4 && (*sb == 'n' && !strncmp(sb, "name", 4) || *sb == 't' && !strncmp(sb, "type", 4)))
290
{
291
sb = *sb == 'n' ? tsp->name : tsp->type;
292
se = sb + strlen(sb);
293
}
294
else if (miscget(tsp, sb, 1, &sb, NiL))
295
for (se = sb; *se && !isspace(*se); se++);
296
else sb = se = "";
297
*st = c;
298
}
299
else sb = se = "";
300
}
301
}
302
}
303
switch (x)
304
{
305
case HASHKEY4('b','i','a','s'):
306
return(osp ? osp->bias == sp->bias : op ? miscop(sp->bias, op, strton(cp, e, NiL, 100)) : sp->bias);
307
case HASHKEY3('c','p','u'):
308
return(osp ? osp->cpu == sp->cpu : sp->cpu);
309
case HASHKEY3('d','a','y'):
310
return(state.tm->tm_wday);
311
case HASHKEY3('g','i','d'):
312
x = 0;
313
if (sb)
314
{
315
gid_t gid;
316
317
*e = ee;
318
if (c = *se) *se = 0;
319
do
320
{
321
if (ee = strchr(sb, '|')) *ee = 0;
322
gid = strgid(sb);
323
if (sb = ee) *sb++ = '|';
324
for (no = 0; state.gids[no] != (gid_t)-1; no++)
325
if (gid == state.gids[no])
326
{
327
x = 1;
328
break;
329
}
330
} while (!x && sb);
331
if (c) *se = c;
332
}
333
return(miscop(1, op, x));
334
case HASHKEY4('h','o','u','r'):
335
return(state.tm->tm_hour);
336
case HASHKEY4('i','d','l','e'):
337
STATS(sp, osp);
338
return(osp ? osp->stat.idle == sp->stat.idle : op ? miscop(sp->stat.idle, op, strelapsed(cp, e, 1)) : sp->stat.idle);
339
case HASHKEY4('j','o','b','s'):
340
return(osp ? osp->running == sp->running : sp->running);
341
case HASHKEY4('l','o','a','d'):
342
STATS(sp, osp);
343
return(osp ? (osp->stat.load / osp->scale) == (sp->stat.load / sp->scale) : op ? miscop(sp->stat.load / sp->scale, op, strton(cp, e, NiL, 100)) : sp->stat.load / sp->scale);
344
case HASHKEY3('m','i','n'):
345
return(state.tm->tm_min);
346
case HASHKEY6('m','i','n','i','d','l'):
347
return(osp ? osp->idle == sp->idle : op ? miscop(sp->idle, op, strelapsed(cp, e, 1)) : sp->idle);
348
case HASHKEY4('n','a','m','e'):
349
if (sb)
350
{
351
*e = ee;
352
return(misccmp(sp->name, op, sb, se));
353
}
354
if (osp) return(streq(osp->name, sp->name));
355
return(*sp->name != 0);
356
case HASHKEY4('o','p','e','n'):
357
return(osp ? (!osp->fd) == (!sp->fd) : sp->fd);
358
case HASHKEY6('r','a','t','i','n','g'):
359
return(osp ? osp->rating == sp->rating : op ? miscop(sp->rating, op, strton(cp, e, NiL, 100)) : sp->rating);
360
case HASHKEY4('t','y','p','e'):
361
if (sb)
362
{
363
*e = ee;
364
return(misccmp(sp->type, op, sb, se));
365
}
366
if (osp) return(streq(osp->type, sp->type));
367
return(*sp->type != 0);
368
case HASHKEY3('u','i','d'):
369
x = 0;
370
if (sb)
371
{
372
uid_t uid;
373
374
*e = ee;
375
if (c = *se) *se = 0;
376
do
377
{
378
if (ee = strchr(sb, '|')) *ee = 0;
379
uid = struid(sb);
380
if (sb = ee) *sb++ = '|';
381
if (uid == state.uid)
382
{
383
x = 1;
384
break;
385
}
386
} while (sb);
387
if (c) *se = c;
388
}
389
return(miscop(1, op, x));
390
case HASHKEY2('u','p'):
391
STATS(sp, osp);
392
return(osp ? osp->stat.up == sp->stat.up : sp->stat.up);
393
}
394
}
395
cp = sp->misc;
396
for (;;)
397
{
398
if (set) *e = cp;
399
np = bp;
400
while (*np++ == *cp++)
401
if (np >= s)
402
{
403
if (*cp == 0 || *cp == ' ')
404
{
405
if (set && rep)
406
{
407
replace:
408
np = *e;
409
if (*cp++)
410
while (*np = *cp++) np++;
411
add:
412
if (!no && np < rep)
413
{
414
cp = np;
415
if (np > sp->misc) *np++ = ' ';
416
for (;;)
417
{
418
if (np >= rep)
419
{
420
np = cp;
421
break;
422
}
423
if (!(*np = *bp++) || isspace(*np)) break;
424
np++;
425
}
426
}
427
*np = 0;
428
}
429
return(1);
430
}
431
if (*cp++ == '=')
432
{
433
if (set)
434
{
435
if (rep)
436
{
437
while (*cp && *cp != ' ') cp++;
438
goto replace;
439
}
440
*e = cp;
441
return(1);
442
}
443
if (sb)
444
{
445
*e = ee;
446
for (np = cp; *np && *np != ' '; np++);
447
c = *np;
448
*np = 0;
449
set = misccmp(cp, op, sb, se);
450
*np = c;
451
return(set);
452
}
453
if (osp)
454
{
455
if (!miscget(osp, bp, 1, &bp, NiL)) return(0);
456
for (np = cp; *np && *np != ' '; np++);
457
return(!strncmp(bp, cp, np - cp));
458
}
459
set = strton(cp, &bp, NiL, 0);
460
if (*bp && *bp != ' ') set = 1;
461
return(set);
462
}
463
break;
464
}
465
cp--;
466
for (;;)
467
{
468
if (!*cp)
469
{
470
if (set && rep)
471
{
472
np = cp;
473
goto add;
474
}
475
if (sb)
476
{
477
*e = ee;
478
return(misccmp("", op, sb, se));
479
}
480
if (osp) return(!miscget(osp, bp, 1, &bp, NiL));
481
return(0);
482
}
483
if (*cp++ == ' ') break;
484
}
485
}
486
}
487
return(0);
488
}
489
490
/*
491
* parse host attributes from s into p
492
* d points to optional default attributes
493
*/
494
495
void
496
attributes(register char* s, register Coattr_t* p, Coattr_t* d)
497
{
498
register char* b;
499
register char* v;
500
char* e;
501
char* r;
502
char* u;
503
int n;
504
int m;
505
int c;
506
int t;
507
int q;
508
int expr;
509
unsigned long x;
510
Coshell_t* sp;
511
512
if (d) *p = *d;
513
else p->set = p->global.set = 0;
514
if (s)
515
{
516
expr = 0;
517
for (;;)
518
{
519
while (isspace(*s) || *s == ',') s++;
520
if (!(t = *(b = s)) || t == '#') break;
521
r = v = 0;
522
m = 0;
523
x = 0;
524
for (;;)
525
{
526
switch (c = *s++)
527
{
528
case '=':
529
if (*s != '=')
530
{
531
if (!v)
532
{
533
v = s;
534
if ((q = *s) == '"' || q == '\'')
535
{
536
v++;
537
while (*++s && *s != q)
538
if (*s == '\\' && *(s + 1)) s++;
539
n = s - v;
540
if (*s) s++;
541
break;
542
}
543
}
544
continue;
545
}
546
/*FALLTHROUGH*/
547
case '|':
548
case '&':
549
case '<':
550
case '>':
551
case '!':
552
case '(':
553
case ')':
554
if (!v)
555
{
556
v = s;
557
t = '*';
558
if (!expr)
559
{
560
expr = 2;
561
if (p->set & SETMISC) u = p->misc;
562
}
563
}
564
continue;
565
case '@':
566
if (!r) r = s;
567
continue;
568
case 0:
569
case ',':
570
case ' ':
571
case '\t':
572
case '\n':
573
if (!v)
574
{
575
v = b;
576
t = (p->set & SETNAME) ? '*' : 'n';
577
}
578
n = s - v - 1;
579
if (!c) s--;
580
break;
581
default:
582
if (m++ < HASHKEYMAX)
583
{
584
if (m == (s - b))
585
{
586
if (islower(c))
587
x = HASHKEYPART(x, c);
588
else
589
{
590
if (isalnum(c) || c == '_')
591
x = 0;
592
m = HASHKEYMAX;
593
}
594
}
595
else m = 6;
596
}
597
continue;
598
}
599
break;
600
}
601
if (r && t != '*')
602
{
603
v = r;
604
m = v[n];
605
v[n] = 0;
606
sp = search(GET, v, NiL, NiL);
607
v[n] = m;
608
if (!sp) continue;
609
}
610
else sp = 0;
611
if (v == b) x = (p->set & SETNAME) ? 0 : HASHKEY4('n','a','m','e');
612
switch (x)
613
{
614
case HASHKEY6('a','c','c','e','s','s'):
615
p->set |= SETACCESS;
616
if (sp) p->access = sp->access;
617
else
618
{
619
static String_t save;
620
621
p->access = savestring(&save, v, n);
622
}
623
continue;
624
case HASHKEY4('b','i','a','s'):
625
p->set |= SETBIAS;
626
p->bias = sp ? sp->bias : strton(v, NiL, NiL, 100);
627
continue;
628
case HASHKEY4('b','u','s','y'):
629
if (!sp)
630
{
631
p->global.set |= SETBUSY;
632
p->global.busy = strelapsed(v, NiL, 1);
633
}
634
continue;
635
case HASHKEY6('b','y','p','a','s','s'):
636
p->set |= SETBYPASS;
637
if (sp) p->bypass = sp->bypass;
638
else
639
{
640
static String_t save;
641
642
p->bypass = savestring(&save, v, n);
643
}
644
continue;
645
case HASHKEY3('c','p','u'):
646
if (p->cpu = sp ? sp->cpu : (int)strtol(v, NiL, 0)) p->set |= SETCPU;
647
continue;
648
case HASHKEY5('d','e','b','u','g'):
649
if (!sp)
650
{
651
p->global.set |= SETDEBUG;
652
p->global.debug = -strton(v, NiL, NiL, 0);
653
}
654
continue;
655
case HASHKEY6('d','i','s','a','b','l'):
656
if (!sp)
657
{
658
p->global.set |= SETDISABLE;
659
p->global.disable = strelapsed(v, NiL, 1);
660
}
661
continue;
662
case HASHKEY4('f','i','l','e'):
663
if (!sp)
664
{
665
static String_t save;
666
667
p->global.set |= SETFILE;
668
p->global.file = savestring(&save, v, n);
669
}
670
continue;
671
case HASHKEY5('g','r','a','c','e'):
672
if (!sp)
673
{
674
p->global.set |= SETGRACE;
675
p->global.grace = strelapsed(v, NiL, 1);
676
}
677
continue;
678
case HASHKEY6('i','d','e','n','t','i'):
679
if (!sp)
680
{
681
static String_t save;
682
683
if (streq(v, "0")) n = strlen(v = "-");
684
else if (streq(v, "1")) n = strlen(v = "[ %s ]\n");
685
p->global.set |= SETIDENTIFY;
686
if (p->global.identify = savestring(&save, v, n))
687
stresc(p->global.identify);
688
}
689
continue;
690
case HASHKEY4('i','d','l','e'):
691
case HASHKEY6('m','i','n','i','d','l'):
692
p->set |= SETIDLE;
693
p->idle = sp ? sp->idle : strelapsed(v, NiL, 1);
694
continue;
695
case HASHKEY6('i','g','n','o','r','e'):
696
p->set |= SETIGNORE;
697
p->ignore = sp ? (sp->flags & IGN) : (int)strtol(v, NiL, 0);
698
continue;
699
case HASHKEY5('l','a','b','e','l'):
700
if (!sp && n)
701
{
702
p->set |= SETLABEL;
703
if (n >= sizeof(p->label))
704
{
705
v += n - sizeof(p->label);
706
n = sizeof(p->label) - 1;
707
}
708
memcpy(p->label, v, n);
709
p->label[n] = 0;
710
}
711
continue;
712
case HASHKEY6('m','a','x','i','d','l'):
713
if (!sp)
714
{
715
p->global.maxidle = (int)strtol(v, NiL, 0);
716
p->global.set |= SETMAXIDLE;
717
}
718
continue;
719
case HASHKEY6('m','a','x','l','o','a'):
720
if (!sp && (p->global.maxload = strton(v, NiL, NiL, 100)) >= 0)
721
p->global.set |= SETMAXLOAD;
722
continue;
723
case HASHKEY6('m','i','g','r','a','t'):
724
if (!sp)
725
{
726
static String_t save;
727
728
p->global.set |= SETMIGRATE;
729
p->global.migrate = savestring(&save, v, n);
730
}
731
continue;
732
case HASHKEY4('n','a','m','e'):
733
p->set |= SETNAME;
734
copystring(p->name, sizeof(p->name), sp ? sp->name : v, sp ? 0 : n);
735
continue;
736
case HASHKEY6('p','e','r','c','p','u'):
737
if (!sp && (p->global.percpu = (int)strtol(v, NiL, 0)) > 0)
738
{
739
if (p->global.percpu > (state.jobmax - state.job + 1))
740
p->global.percpu = state.jobmax - state.job + 1;
741
p->global.set |= SETPERCPU;
742
}
743
continue;
744
case HASHKEY6('p','e','r','h','o','s'):
745
if (!sp && (p->global.perhost = (int)strtol(v, NiL, 0)) > 0)
746
{
747
if (p->global.perhost > (state.jobmax - state.job + 1))
748
p->global.perhost = state.jobmax - state.job + 1;
749
p->global.set |= SETPERHOST;
750
}
751
continue;
752
case HASHKEY6('p','e','r','s','e','r'):
753
if (!sp && (p->global.perserver = (int)strtol(v, NiL, 0)) >= 0)
754
{
755
if (p->global.perserver > (state.jobmax - state.job + 1))
756
p->global.perserver = state.jobmax - state.job + 1;
757
p->global.set |= SETPERSERVER;
758
}
759
continue;
760
case HASHKEY6('p','e','r','u','s','e'):
761
if (!sp && (p->global.peruser = (int)strtol(v, NiL, 0)) > 0)
762
{
763
if (p->global.peruser > (state.jobmax - state.job + 1))
764
p->global.peruser = state.jobmax - state.job + 1;
765
p->global.set |= SETPERUSER;
766
}
767
continue;
768
case HASHKEY4('p','o','o','l'):
769
if (!sp && (p->global.pool = (int)strtol(v, NiL, 0)) > 0)
770
p->global.set |= SETPOOL;
771
continue;
772
case HASHKEY6('p','r','o','f','i','l'):
773
if (!sp)
774
{
775
static String_t save;
776
777
p->global.set |= SETPROFILE;
778
p->global.profile = savestring(&save, v, n);
779
}
780
continue;
781
case HASHKEY6('r','a','t','i','n','g'):
782
if (p->rating = sp ? sp->rating : strton(v, NiL, NiL, 100)) p->set |= SETRATING;
783
continue;
784
case HASHKEY6('r','e','m','o','t','e'):
785
if (p->set & SETNAME)
786
{
787
p->set |= SETREMOTE;
788
copystring(p->remote, sizeof(p->remote), v, n);
789
}
790
else
791
{
792
static String_t save;
793
794
p->global.set |= SETREMOTE;
795
p->global.remote = savestring(&save, v, n);
796
}
797
continue;
798
case HASHKEY5('s','c','a','l','e'):
799
if (p->scale = sp ? sp->scale : (int)strtol(v, NiL, 0)) p->set |= SETSCALE;
800
continue;
801
case HASHKEY6('s','c','h','e','d','u'):
802
if (!sp)
803
{
804
static String_t save;
805
806
p->global.set |= SETSCHEDULE;
807
p->global.schedule = savestring(&save, v, n);
808
}
809
continue;
810
case HASHKEY6('s','e','r','v','i','c'):
811
continue;
812
case HASHKEY5('s','h','e','l','l'):
813
if (p->set & SETNAME)
814
{
815
p->set |= SETSHELL;
816
copystring(p->shell, sizeof(p->shell), v, n);
817
}
818
else
819
{
820
static String_t save;
821
822
p->global.set |= SETSHELL;
823
p->global.shell = savestring(&save, v, n);
824
}
825
continue;
826
case HASHKEY4('s','t','a','t'):
827
if ((v - b) > 6 && *(b + 4) == '.')
828
{
829
if ((--v - (b += HASHKEYMAX - 1)) > HASHKEYMAX)
830
v = b + HASHKEYMAX;
831
while (b < v)
832
{
833
if (islower(q = *b++))
834
x = HASHKEYPART(x, q);
835
else
836
{
837
if (isalnum(q) || q == '_')
838
x = 0;
839
break;
840
}
841
}
842
switch (x)
843
{
844
case HASHKEY4('i','d','l','e'):
845
p->global.set |= SETIDLE;
846
p->stat.idle = strelapsed(v, NiL, 1);
847
break;
848
case HASHKEY4('l','o','a','d'):
849
p->global.set |= SETLOAD;
850
p->stat.load = strton(v, NiL, NiL, 100);
851
break;
852
case HASHKEY6('u','p','d','a','t','e'):
853
p->global.set |= SETUPDATE;
854
p->stat.up = cs.time + strelapsed(v, NiL, 1);
855
break;
856
case HASHKEY5('u','s','e','r','s'):
857
p->global.set |= SETUSERS;
858
p->stat.users = strton(v, NiL, NiL, 0);
859
break;
860
}
861
continue;
862
}
863
break;
864
case HASHKEY4('t','y','p','e'):
865
p->set |= SETTYPE;
866
copystring(p->type, sizeof(p->type), sp ? sp->type : v, sp ? 0 : n);
867
continue;
868
}
869
if (!(p->set & SETMISC))
870
{
871
p->set |= SETMISC;
872
u = p->misc;
873
}
874
if (!sp) n = s - b - (*s != 0);
875
else if (miscget(sp, b, 1, &e, NiL))
876
{
877
for (v = b = e; *b && *b != ' '; b++);
878
n = v - b;
879
}
880
else n = 0;
881
if (n > 0 && u + n + expr < p->misc + sizeof(p->misc) - 1)
882
{
883
if (expr)
884
{
885
if (expr == 4)
886
{
887
*u++ = '&';
888
*u++ = '&';
889
}
890
else expr = 4;
891
*u++ = '(';
892
}
893
else if (u != p->misc) *u++ = ' ';
894
memcpy(u, b, n);
895
u += n;
896
if (expr) *u++ = ')';
897
}
898
*u = 0;
899
}
900
}
901
}
902
903
/*
904
* add misc attributes in s to sp
905
*/
906
907
void
908
miscadd(Coshell_t* sp, register char* s)
909
{
910
char* tp;
911
912
for (;;)
913
{
914
while (isspace(*s)) s++;
915
if (!*s) return;
916
miscget(sp, s, 1, &tp, sp->misc + sizeof(sp->misc) - 1);
917
while (!isspace(*s)) if (!*s++) return;
918
}
919
}
920
921
/*
922
* evaluate miscmatch() expression operand
923
*/
924
925
static long
926
misceval(const char* s, char** e, void* handle)
927
{
928
if (!s)
929
{
930
message((-3, "attribute: %s", *e));
931
return(0);
932
}
933
return(miscget((Coshell_t*)handle, s, 0, e, NiL));
934
}
935
936
/*
937
* evaluate misc attribute expression p on shell info sp
938
*/
939
940
int
941
miscmatch(Coshell_t* sp, char* p)
942
{
943
return(strexpr(p, NiL, misceval, sp) != 0);
944
}
945
946
/*
947
* format pseudo-float
948
*/
949
950
#define PFSIZE 9
951
952
char*
953
fmtfloat(int n)
954
{
955
static char buf[4][PFSIZE];
956
static int inx;
957
958
if (++inx >= elementsof(buf)) inx = 0;
959
sfsprintf(buf[inx], PFSIZE, "%d.%02d", n / 100, n % 100);
960
return(buf[inx]);
961
}
962
963