386BSD 0.1 development
[unix-history] / usr / othersrc / public / zsh-2.2 / src / params.c
CommitLineData
dbf02a84
WJ
1/*
2 *
3 * params.c - parameters
4 *
5 * This file is part of zsh, the Z shell.
6 *
7 * This software is Copyright 1992 by Paul Falstad
8 *
9 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
10 * use this software as long as: there is no monetary profit gained
11 * specifically from the use or reproduction of this software, it is not
12 * sold, rented, traded or otherwise marketed, and this copyright notice is
13 * included prominently in any copy made.
14 *
15 * The author make no claims as to the fitness or correctness of this software
16 * for any use whatsoever, and it is provided as is. Any use of this software
17 * is at the user's own risk.
18 *
19 */
20
21#include "zsh.h"
22#include <pwd.h>
23
24#define new(X) (X=(vptr)alloc(sizeof(*(X))))
25
26static Param argvparam;
27
28struct iparam {
29 struct hashnode *next; int canfree; char *nam; /* hash data */
30 void *value;
31 int (*func1)(); /* set func */
32 int (*func2)(); /* get func */
33 int ct; /* output base or field width */
34 int flags;
35 vptr data; /* used by getfns */
36 char *env; /* location in environment, if exported */
37 char *ename; /* name of corresponding environment var */
38 };
39
40#define IFN(X) ((int (*)())(X))
41
42/* put predefined params in hash table */
43
44void setupparams() /**/
45{
46static struct iparam pinit[] = {
47#define IPDEF1(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),10,\
48 PMFLAG_i|PMFLAG_SPECIAL|D,NULL,NULL,NULL}
49 IPDEF1("#",poundgetfn,IFN(nullsetfn),PMFLAG_r),
50 IPDEF1("ARGC",poundgetfn,IFN(nullsetfn),PMFLAG_r),
51 IPDEF1("ERRNO",errnogetfn,IFN(nullsetfn),PMFLAG_r),
52 IPDEF1("GID",gidgetfn,IFN(nullsetfn),PMFLAG_r),
53 IPDEF1("HISTSIZE",histsizegetfn,histsizesetfn,0),
54 IPDEF1("LITHISTSIZE",lithistsizegetfn,lithistsizesetfn,0),
55 IPDEF1("RANDOM",randomgetfn,randomsetfn,0),
56 IPDEF1("SECONDS",secondsgetfn,secondssetfn,0),
57 IPDEF1("UID",uidgetfn,IFN(nullsetfn),PMFLAG_r),
58
59#define IPDEF2(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),0,\
60 PMFLAG_SPECIAL|D,NULL,NULL,NULL}
61 IPDEF2("-",dashgetfn,IFN(nullsetfn),PMFLAG_r),
62 IPDEF2("HISTCHARS",histcharsgetfn,histcharssetfn,0),
63 IPDEF2("HOME",homegetfn,homesetfn,0),
64 IPDEF2("TERM",termgetfn,termsetfn,0),
65 IPDEF2("WORDCHARS",wordcharsgetfn,wordcharssetfn,0),
66 IPDEF2("IFS",ifsgetfn,ifssetfn,0),
67 IPDEF2("_",underscoregetfn,IFN(nullsetfn),PMFLAG_r),
68
69#define IPDEF3(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strconstgetfn),0,PMFLAG_r|\
70 PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
71 IPDEF3("HOSTTYPE",HOSTTYPE),
72 IPDEF3("VERSION",VERSIONSTR),
73
74#define IPDEF4(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(intvargetfn),10,\
75 PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
76 IPDEF4("!",&lastpid),
77 IPDEF4("$",&mypid),
78 IPDEF4("?",&lastval),
79 IPDEF4("status",&lastval),
80 IPDEF4("LINENO",&lineno),
81 IPDEF4("PPID",&ppid),
82
83#define IPDEF5(A,B) {NULL,0,A,NULL,IFN(intvarsetfn),IFN(intvargetfn),10,\
84 PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
85 IPDEF5("BAUD",&baud),
86 IPDEF5("COLUMNS",&columns),
87 IPDEF5("DIRSTACKSIZE",&dirstacksize),
88 IPDEF5("LINES",&lines),
89 IPDEF5("LISTMAX",&listmax),
90 IPDEF5("LOGCHECK",&logcheck),
91 IPDEF5("MAILCHECK",&mailcheck),
92 IPDEF5("OPTIND",&zoptind),
93 IPDEF5("PERIOD",&period),
94 IPDEF5("REPORTTIME",&reporttime),
95 IPDEF5("SAVEHIST",&savehist),
96 IPDEF5("SHLVL",&shlvl),
97 IPDEF5("TMOUT",&tmout),
98
99#define IPDEF6(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strvargetfn),0,\
100 PMFLAG_r|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
101 IPDEF6("LOGNAME",&logname),
102 IPDEF6("PWD",&pwd),
103 IPDEF6("TTY",&ttystrname),
104 IPDEF6("USERNAME",&username),
105
106#define IPDEF7(A,B) {NULL,0,A,NULL,IFN(strvarsetfn),IFN(strvargetfn),0,\
107 PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
108 IPDEF7("FCEDIT",&fceditparam),
109 IPDEF7("HOST",&hostnam),
110 IPDEF7("OLDPWD",&oldpwd),
111 IPDEF7("OPTARG",&optarg),
112 IPDEF7("MAIL",&mailfile),
113 IPDEF7("NULLCMD",&nullcmd),
114 IPDEF7("POSTEDIT",&postedit),
115 IPDEF7("prompt",&prompt),
116 IPDEF7("PROMPT",&prompt),
117 IPDEF7("PROMPT2",&prompt2),
118 IPDEF7("PROMPT3",&prompt3),
119 IPDEF7("PROMPT4",&prompt4),
120 IPDEF7("READNULLCMD",&readnullcmd),
121 IPDEF7("RPROMPT",&rprompt),
122 IPDEF7("PS1",&prompt),
123 IPDEF7("PS2",&prompt2),
124 IPDEF7("PS3",&prompt3),
125 IPDEF7("PS4",&prompt4),
126 IPDEF7("RPS1",&rprompt),
127 IPDEF7("SPROMPT",&sprompt),
128 IPDEF7("TIMEFMT",&timefmt),
129 IPDEF7("TMPPREFIX",&tmpprefix),
130 IPDEF7("WATCHFMT",&watchfmt),
131 IPDEF7("0",&argzero),
132
133#define IPDEF8(A,B,C) {NULL,0,A,NULL,IFN(colonarrsetfn),IFN(colonarrgetfn),0,\
134 PMFLAG_SPECIAL,(vptr)C,NULL,B}
135 IPDEF8("CDPATH","cdpath",&cdpath),
136 IPDEF8("FIGNORE","fignore",&fignore),
137 IPDEF8("FPATH","fpath",&fpath),
138 IPDEF8("MAILPATH","mailpath",&mailpath),
139 IPDEF8("MANPATH","manpath",&manpath),
140 IPDEF8("WATCH","watch",&watch),
141 IPDEF8("HOSTS","hosts",&hosts),
142 IPDEF8("PATH",NULL,NULL),
143
144#define IPDEF9(A,B,C) {NULL,0,A,NULL,IFN(arrvarsetfn),IFN(arrvargetfn),0,\
145 PMFLAG_A|PMFLAG_SPECIAL|C,(vptr)B,NULL,NULL}
146 IPDEF9("cdpath",&cdpath,0),
147 IPDEF9("fignore",&fignore,0),
148 IPDEF9("fpath",&fpath,0),
149 IPDEF9("mailpath",&mailpath,0),
150 IPDEF9("manpath",&manpath,0),
151 IPDEF9("watch",&watch,0),
152 IPDEF9("hosts",&hosts,0),
153 IPDEF9("signals",&sigptr,PMFLAG_r),
154 IPDEF9("argv",&pparams,0),
155 IPDEF9("*",&pparams,0),
156 IPDEF9("@",&pparams,0),
157
158#define IPDEF10(A,C,D) {NULL,0,A,NULL,IFN(D),IFN(C),0,\
159 PMFLAG_A|PMFLAG_SPECIAL,NULL,NULL,NULL}
160 IPDEF10("path",pathgetfn,pathsetfn),
161 IPDEF10("hostcmds",nullgetfn,hostcmdssetfn),
162 IPDEF10("optcmds",nullgetfn,optcmdssetfn),
163 IPDEF10("bindcmds",nullgetfn,bindcmdssetfn),
164 IPDEF10("varcmds",nullgetfn,varcmdssetfn),
165 {NULL,}
166 };
167struct iparam *ip;
168
169 for (ip = pinit; ip->nam; ip++) addhperm(ip->nam,ip,paramtab,NULL);
170 argvparam = gethnode("argv",paramtab);
171}
172
173static int unsetflag;
174
175struct param *createparam(name,value,flags) /**/
176char *name;vptr value;int flags;
177{
178struct param *pm;
179char buf[20];
180
181 pm = zcalloc(sizeof *pm);
182 if (isset(ALLEXPORT))
183 flags |= PMFLAG_x;
184 pm->flags = flags;
185 if ((flags & PMTYPE) == PMFLAG_s) {
186 pm->u.str = value;
187 pm->sets.cfn = strsetfn;
188 pm->gets.cfn = strgetfn;
189 } else if ((flags & PMTYPE) == PMFLAG_A) {
190 pm->u.arr = value;
191 pm->sets.afn = arrsetfn;
192 pm->gets.afn = arrgetfn;
193 } else {
194 pm->u.val = (value) ? matheval(value) : 0;
195 pm->sets.ifn = intsetfn;
196 pm->gets.ifn = intgetfn;
197 sprintf(buf,"%ld",pm->u.val);
198 value = buf;
199 }
200 if (flags & PMFLAG_x)
201 pm->env = addenv(name,value);
202 addhnode(ztrdup(name),pm,paramtab,freepm);
203 return pm;
204}
205
206int isident(s) /**/
207char *s;
208{
209char *ss;
210
211 for (ss = s; *ss; ss++) if (!iident(*ss)) break;
212 if (!*ss || *ss == '[') return 1;
213 if (*s == Quest)
214 *s = '?';
215 else if (*s == Pound)
216 *s = '#';
217 else if (*s == String || *s == Qstring)
218 *s = '$';
219 else if (*s == Star)
220 *s = '*';
221 if (*s == '#' || *s == '-' || *s == '?' || *s == '$' || *s == '_' ||
222 *s == '!' || *s == '@' || *s == '*')
223 return 1;
224 return 0;
225}
226
227Value getvalue(pptr,bracks) /**/
228char **pptr;int bracks;
229{
230char *s = *pptr,*t = *pptr;
231char sav;
232Value v;
233
234 if (idigit(*s)) while (idigit(*s)) s++;
235 else if (iident(*s)) while (iident(*s)) s++;
236 else if (*s == Quest) *s++ = '?';
237 else if (*s == Pound) *s++ = '#';
238 else if (*s == String) *s++ = '$';
239 else if (*s == Qstring) *s++ = '$';
240 else if (*s == Star) *s++ = '*';
241 else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
242 *s == '_' || *s == '!' || *s == '@' || *s == '*') s++;
243 else return NULL;
244 if (sav = *s) *s = '\0';
245 if (idigit(*t) && *t != '0') {
246 v = (Value) hcalloc(sizeof *v);
247 v->pm = argvparam;
248 v->a = v->b = atoi(t)-1;
249 if (sav)
250 *s = sav;
251 } else {
252 struct param *pm;
253 int isvarat = !strcmp(t, "@");
254
255 pm = gethnode(t,paramtab);
256 if (sav)
257 *s = sav;
258 *pptr = s;
259 if (!pm)
260 return NULL;
261 v = hcalloc(sizeof *v);
262 if (pmtype(pm) == PMFLAG_A)
263 v->isarr = isvarat ? -1 : 1;
264 v->pm = pm;
265 v->a = 0; v->b = -1;
266 if (bracks && (*s == '[' || *s == Inbrack)) {
267 int a,b;
268 char *olds = s,*t;
269
270 *s++ = '[';
271 for (t = s; *t && *t != ']' && *t != Outbrack; t++)
272 if (itok(*t))
273 *t = ztokens[*t-Pound];
274 if (*t == Outbrack)
275 *t = ']';
276 if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
277 if (v->isarr) v->isarr = (s[0] == '*') ? 1 : -1;
278 v->a = 0;
279 v->b = -1;
280 s += 2;
281 } else {
282 a = mathevalarg(s,&s);
283 if (a > 0) a--;
284 if (*s == ',' || *s == Comma) {
285 s++;
286 b = mathevalarg(s,&s);
287 if (b > 0) b--;
288 } else
289 b = a;
290 if (*s == ']') {
291 s++;
292 if (v->isarr && a == b)
293 v->isarr = 0;
294 v->a = a;
295 v->b = b;
296 } else
297 s = olds;
298 }
299 }
300 }
301 if (!bracks && *s)
302 return NULL;
303 *pptr = s;
304 return v;
305}
306
307char *getstrvalue(v) /**/
308Value v;
309{
310char *s,**ss;
311static char buf[20];
312
313 if (!v)
314 return "";
315 if (pmtype(v->pm) != PMFLAG_A) {
316 if ((pmtype(v->pm) == PMFLAG_i))
317 convbase(s = buf,v->pm->gets.ifn(v->pm),v->pm->ct);
318 else
319 s = v->pm->gets.cfn(v->pm);
320 if (v->a == 0 && v->b == -1) return s;
321 if (v->a < 0) v->a += strlen(s);
322 if (v->b < 0) v->b += strlen(s);
323 s = (v->a > strlen(s)) ? strdup("") : strdup(s+v->a);
324 if (v->b < v->a) s[0] = '\0';
325 else if (v->b-v->a < strlen(s)) s[v->b-v->a+1] = '\0';
326 return s;
327 }
328 if (v->isarr) return spacejoin(v->pm->gets.afn(v->pm));
329
330 ss = v->pm->gets.afn(v->pm);
331 if (v->a < 0) v->a += arrlen(ss);
332 s = (v->a >= arrlen(ss) || v->a < 0) ? "" : ss[v->a];
333 return s;
334}
335
336char **getarrvalue(v) /**/
337Value v;
338{
339char **s;
340static char *nular[] = { "", NULL };
341
342 if (!v)
343 return arrdup(nular);
344 s = v->pm->gets.afn(v->pm);
345 if (v->a == 0 && v->b == -1) return s;
346 if (v->a < 0) v->a += arrlen(s);
347 if (v->b < 0) v->b += arrlen(s);
348 if (v->a > arrlen(s) || v->a < 0)
349 s = arrdup(nular);
350 else
351 s = arrdup(s)+v->a;
352 if (v->b < v->a) s[0] = NULL;
353 else if (v->b-v->a < arrlen(s)) s[v->b-v->a+1] = NULL;
354 return s;
355}
356
357long getintvalue(v) /**/
358Value v;
359{
360char **ss;
361
362 if (!v || v->isarr)
363 return 0;
364 if (pmtype(v->pm) != PMFLAG_A) {
365 if (pmtype(v->pm) == PMFLAG_i)
366 return v->pm->gets.ifn(v->pm);
367 return atol(v->pm->gets.cfn(v->pm));
368 }
369 ss = v->pm->gets.afn(v->pm);
370 if (v->a < 0) v->a += arrlen(ss);
371 if (v->a < 0 || v->a > arrlen(ss)) return 0;
372 return atol(ss[v->a]);
373}
374
375void setstrvalue(v,val) /**/
376Value v;char *val;
377{
378char *s;
379
380 if (v->pm->flags & PMFLAG_r) {
381 free(val);
382 return;
383 }
384 if ((s = v->pm->env) && val)
385 v->pm->env = replenv(v->pm->env,val);
386 switch (pmtype(v->pm)) {
387 case PMFLAG_s:
388 if (v->a == 0 && v->b == -1)
389 (v->pm->sets.cfn)(v->pm,val);
390 else {
391 char *z,*y,*x;
392
393 z = strdup((v->pm->gets.cfn)(v->pm));
394 if (v->a < 0) {
395 v->a += strlen(z);
396 if (v->a < 0) v->a = 0;
397 }
398 if (v->a > strlen(z)) v->a = strlen(z);
399 if (v->b < 0) v->b += strlen(z);
400 if (v->b < v->a) v->b = v->a;
401 z[v->a] = '\0';
402 y = z+v->b+1;
403 x = zalloc(strlen(z)+strlen(y)+strlen(val)+1);
404 strcpy(x,z);
405 strcat(x,val);
406 strcat(x,y);
407 (v->pm->sets.cfn)(v->pm,x);
408 }
409 if (v->pm->flags & (PMFLAG_L|PMFLAG_R|PMFLAG_Z) && !v->pm->ct)
410 v->pm->ct = strlen(val);
411 break;
412 case PMFLAG_i:
413 (v->pm->sets.ifn)(v->pm,matheval(val));
414 if (!v->pm->ct && lastbase != 1)
415 v->pm->ct = lastbase;
416 free(val);
417 break;
418 case PMFLAG_A:
419 if (v->a != v->b)
420 zerr("illegal array assignment",NULL,0);
421 else {
422 char **ss = (v->pm->gets.afn)(v->pm);
423 int ac,ad,t0;
424
425 ac = arrlen(ss);
426 if (v->a < 0) {
427 v->a += ac;
428 if (v->a < 0) v->a = 0;
429 }
430 if (v->a >= ac) {
431 char **st = ss;
432
433 ad = v->a+1;
434 ss = zalloc((ad+1)*sizeof *ss);
435 memcpy(ss,st,(ad+1)*sizeof *ss);
436 for (t0 = 0; t0 != ac; t0++)
437 ss[t0] = ztrdup(ss[t0]);
438 while (ac < ad)
439 ss[ac++] = ztrdup("");
440 ss[ac] = NULL;
441 }
442 if (ss[v->a]) free(ss[v->a]);
443 ss[v->a] = val;
444 (v->pm->sets.afn)(v->pm,ss);
445 }
446 break;
447 }
448}
449
450void setintvalue(v,val) /**/
451Value v;long val;
452{
453char buf[20];
454
455 if (v->pm->flags & PMFLAG_r)
456 return;
457 if (v->pm->env) {
458 sprintf(buf,"%ld",val);
459 v->pm->env = replenv(v->pm->env,buf);
460 }
461 switch (pmtype(v->pm))
462 {
463 case PMFLAG_s:
464 sprintf(buf,"%ld",val);
465 (v->pm->sets.cfn)(v->pm,ztrdup(buf));
466 break;
467 case PMFLAG_i:
468 (v->pm->sets.ifn)(v->pm,val);
469 if (!v->pm->ct && lastbase != -1)
470 v->pm->ct = lastbase;
471 break;
472 case PMFLAG_A:
473 zerr("attempt to assign integer to array",NULL,0);
474 break;
475 }
476}
477
478void setintenv(s,val) /**/
479char *s; long val;
480{
481Param pm;
482char buf[20];
483
484 if ((pm = gethnode(s,paramtab)) && pm->env) {
485 sprintf(buf,"%ld",val);
486 pm->env = replenv(pm->env,buf);
487 }
488}
489
490void setarrvalue(v,val) /**/
491Value v;char **val;
492{
493 if (v->pm->flags & PMFLAG_r)
494 return;
495 if (pmtype(v->pm) != PMFLAG_A)
496 {
497 zerr("attempt to assign array value to non-array",NULL,0);
498 return;
499 }
500 (v->pm->sets.afn)(v->pm,val);
501}
502
503char *getsparamval(s,l) /**/
504char *s;int l;
505{
506char sav,*t = s;
507Value v;
508
509 if (sav = t[l])
510 t[l] = '\0';
511 if (!(v = getvalue(&s,0)))
512 return NULL;
513 t[l] = sav;
514 t = getstrvalue(v);
515 return t;
516}
517
518long getiparam(s) /**/
519char *s;
520{
521Value v;
522
523 if (!(v = getvalue(&s,0)))
524 return 0;
525 return getintvalue(v);
526}
527
528char *getsparam(s) /**/
529char *s;
530{
531Value v;
532
533 if (!(v = getvalue(&s,0)))
534 return NULL;
535 return getstrvalue(v);
536}
537
538char **getaparam(s) /**/
539char *s;
540{
541Value v;
542
543 if (!(v = getvalue(&s,0))) return NULL;
544 return getarrvalue(v);
545}
546
547Param setsparam(s,val) /**/
548char *s;char *val;
549{
550Value v;
551char *t = s;
552
553 if (!isident(s)) {
554 zerr("not an identifier: %s",s,0);
555 free(val);
556 return NULL;
557 }
558 if (!(v = getvalue(&s,1)) || *s)
559 return createparam(t,val,PMFLAG_s);
560 if ((v->pm->flags & PMTYPE) != PMFLAG_s &&
561 !(v->pm->flags & PMFLAG_SPECIAL)) {
562 unsetparam(s);
563 return createparam(t,val,PMFLAG_s);
564 }
565 setstrvalue(v,val);
566 return v->pm;
567}
568
569Param setaparam(s,val) /**/
570char *s;char **val;
571{
572Value v;
573char *t = s;
574
575 if (!isident(s))
576 {
577 zerr("not an identifier: %s",s,0);
578 return NULL;
579 }
580 if (!(v = getvalue(&s,1)) || *s)
581 return createparam(t,val,PMFLAG_A);
582 if ((v->pm->flags & PMTYPE) != PMFLAG_A &&
583 !(v->pm->flags & PMFLAG_SPECIAL)) {
584 unsetparam(s);
585 return createparam(t,val,PMFLAG_A);
586 }
587 setarrvalue(v,val);
588 return v->pm;
589}
590
591Param setiparam(s,val) /**/
592char *s;long val;
593{
594Value v;
595char *t = s;
596Param pm;
597
598 if (!isident(s))
599 {
600 zerr("not an identifier: %s",s,0);
601 return NULL;
602 }
603 if (!(v = getvalue(&s,0)))
604 {
605 pm = createparam(t,NULL,PMFLAG_i);
606 pm->u.val = val;
607 return pm;
608 }
609 setintvalue(v,val);
610 return v->pm;
611}
612
613void unsetparam(s) /**/
614char *s;
615{
616Param pm;
617
618 if (!(pm = gethnode(s,paramtab)))
619 return;
620 if (pm->flags & PMFLAG_r)
621 return;
622 unsetflag = 1;
623 switch (pmtype(pm))
624 {
625 case 0:
626 (pm->sets.cfn)(pm,ztrdup(""));
627 break;
628 case PMFLAG_i:
629 (pm->sets.ifn)(pm,0);
630 break;
631 case PMFLAG_A:
632 (pm->sets.afn)(pm,mkarray(NULL));
633 break;
634 }
635 if (pmtype(pm) == PMFLAG_s && (pm->flags & PMFLAG_x)) {
636 delenv(pm->env);
637 free(pm->env);
638 }
639 if (!(pm->flags & PMFLAG_SPECIAL))
640 freepm(remhnode(s,paramtab));
641 unsetflag = 0;
642}
643
644void intsetfn(pm,x) /**/
645Param pm;long x;
646{
647 pm->u.val = x;
648}
649
650long intgetfn(pm) /**/
651Param pm;
652{
653 return pm->u.val;
654}
655
656void strsetfn(pm,x) /**/
657Param pm;char *x;
658{
659 if (x)
660 {
661 if (pm->u.str)
662 free(pm->u.str);
663 pm->u.str = x;
664 }
665}
666
667char *strgetfn(pm) /**/
668Param pm;
669{
670 return pm->u.str;
671}
672
673void nullsetfn(pm,x) /**/
674Param pm; char *x;
675{
676 free(x);
677}
678
679void arrsetfn(pm,x) /**/
680Param pm;char **x;
681{
682int ct;
683
684 if (x)
685 {
686 if (pm->u.arr && pm->u.arr != x)
687 freearray(pm->u.arr);
688 pm->u.arr = x;
689 for (ct = 0; *x; x++,ct++);
690 pm->ct = ct;
691 }
692}
693
694char **arrgetfn(pm) /**/
695Param pm;
696{
697 return pm->u.arr;
698}
699
700void intvarsetfn(pm,x) /**/
701Param pm;long x;
702{
703 *((long *) pm->data) = x;
704}
705
706long intvargetfn(pm) /**/
707Param pm;
708{
709 return *((long *) pm->data);
710}
711
712void strvarsetfn(pm,x) /**/
713Param pm;char *x;
714{
715char **q = ((char **) pm->data);
716
717 if (*q) free(*q);
718 *q = x;
719}
720
721void strvarnonullsetfn(pm,x) /**/
722Param pm;char *x;
723{
724char **q = ((char **) pm->data);
725
726 if (*q) free(*q);
727 *q = (x) ? x : ztrdup("");
728}
729
730char *strvargetfn(pm) /**/
731Param pm;
732{
733char *s;
734
735 s = *((char **) pm->data);
736 if (!s) return "";
737 return s;
738}
739
740char *strconstgetfn(pm) /**/
741Param pm;
742{
743 return (char *) pm->data;
744}
745
746void colonarrsetfn(pm,x) /**/
747Param pm;char *x;
748{
749char **s,**t,*u,*up;
750
751 s = colonsplit(x);
752 free(x);
753 if (pm->data != &fignore)
754 for (t = s; *t; t++) {
755 u = *t;
756 if (*u == '~') *u = Tilde;
757 if (*u == '=') *u = Equals;
758 up = hcalloc(strlen(u)+1);
759 strcpy(up,u);
760 u = up;
761 filesub(&u);
762 if (!*u) u = ".";
763 *t = ztrdup(u);
764 }
765 if (pm->data) {
766 freearray(*((char ***) pm->data));
767 *((char ***) pm->data) = s;
768 if (pm->ename)
769 arrfixenv(pm->ename,s);
770 } else {
771 freearray(path);
772 path = s;
773 newcmdnamtab();
774 arrfixenv("PATH",s);
775 }
776}
777
778char *colonarrgetfn(pm) /**/
779Param pm;
780{
781 if ((char **) pm->data)
782 return colonjoin(*(char ***) pm->data);
783 else
784 return colonjoin(path);
785}
786
787char **arrvargetfn(pm) /**/
788Param pm;
789{
790 return *((char ***) pm->data);
791}
792
793void arrvarsetfn(pm,x) /**/
794Param pm;char **x;
795{
796 if ((*(char ***) pm->data) != x)
797 freearray(*(char ***) pm->data);
798 *((char ***) pm->data) = x;
799 if (pm->ename)
800 arrfixenv(pm->ename,x);
801}
802
803char **pathgetfn(pm) /**/
804Param pm;
805{
806 return path;
807}
808
809void pathsetfn(pm,x) /**/
810Param pm;char **x;
811{
812 if (path != x) freearray(path);
813 path = x;
814 newcmdnamtab();
815 arrfixenv("PATH",x);
816}
817
818void hostcmdssetfn(pm,x) /**/
819Param pm;char **x;
820{
821 compctl_process(x,CC_HOSTS|CC_FILES,NULL);
822 freearray(x);
823}
824
825void optcmdssetfn(pm,x) /**/
826Param pm;char **x;
827{
828 compctl_process(x,CC_OPTIONS,NULL);
829 freearray(x);
830}
831
832void bindcmdssetfn(pm,x) /**/
833Param pm;char **x;
834{
835 compctl_process(x,CC_BINDINGS,NULL);
836 freearray(x);
837}
838
839void varcmdssetfn(pm,x) /**/
840Param pm;char **x;
841{
842 compctl_process(x,CC_VARS,NULL);
843 freearray(x);
844}
845
846char **nullgetfn(pm) /**/
847Param pm;
848{
849static char *nl = NULL; return &nl;
850}
851
852void unsettablesetfn(pm,x) /**/
853Param pm;char *x;
854{ ; }
855
856long poundgetfn(pm) /**/
857Param pm;
858{
859 return arrlen(pparams);
860}
861
862long randomgetfn(pm) /**/
863Param pm;
864{
865 return rand() & 0x7fff;
866}
867
868void randomsetfn(pm,v) /**/
869Param pm;long v;
870{
871 srand((unsigned int) v);
872}
873
874long secondsgetfn(pm) /**/
875Param pm;
876{
877 return time(NULL)-shtimer;
878}
879
880void secondssetfn(pm,x) /**/
881Param pm;long x;
882{
883 shtimer = time(NULL)-x;
884}
885
886long uidgetfn(pm) /**/
887Param pm;
888{
889 return getuid();
890}
891
892long gidgetfn(pm) /**/
893Param pm;
894{
895 return getegid();
896}
897
898char *usernamegetfn(pm) /**/
899Param pm;
900{
901struct passwd *pwd;
902
903 pwd = getpwuid(getuid());
904 return pwd->pw_name;
905}
906
907char *hostgetfn(pm) /**/
908Param pm;
909{
910static char hostnam[65];
911static int got = 0;
912
913 if (!got)
914 {
915 gethostname(hostnam,64);
916 hostnam[64] = '\0';
917 got = 1;
918 }
919 return hostnam;
920}
921
922char *ifsgetfn(pm) /**/
923Param pm;
924{
925 return ifs;
926}
927
928void ifssetfn(pm,x) /**/
929Param pm;char *x;
930{
931 if (x) { free(ifs); ifs = x; }
932 inittyptab();
933}
934
935void histsizesetfn(pm,v) /**/
936Param pm;long v;
937{
938 if ((histsiz = v) <= 2) histsiz = 2;
939 resizehistents();
940}
941
942long histsizegetfn(pm) /**/
943Param pm;
944{
945 return histsiz;
946}
947
948void lithistsizesetfn(pm,v) /**/
949Param pm;long v;
950{
951 if ((lithistsiz = v) <= 2) lithistsiz = 2;
952 resizehistents();
953}
954
955long lithistsizegetfn(pm) /**/
956Param pm;
957{
958 return lithistsiz;
959}
960
961void mailchecksetfn(pm,x) /**/
962Param pm;long x;
963{
964 mailcheck = (unsetflag) ? 600 : x;
965}
966
967void pathasetfn(pm,x) /**/
968Param pm;char **x;
969{
970 freearray(path);
971 path = x;
972 newcmdnamtab();
973}
974
975char **pathagetfn(pm) /**/
976Param pm;
977{
978 return path;
979}
980
981long errnogetfn(pm) /**/
982Param pm;
983{
984 return errno;
985}
986
987char *dashgetfn(pm) /**/
988Param pm;
989{
990static char buf[100];
991char *val = buf;
992int t0;
993
994 for (val = buf, t0 = ' ';t0 <= 'z'; t0++)
995 if (opts[t0] == OPT_SET)
996 *val++ = t0;
997 *val = '\0';
998 return buf;
999}
1000
1001void histcharssetfn(pm,x) /**/
1002Param pm;char *x;
1003{
1004 if (x) {
1005 bangchar = x[0];
1006 hatchar = (bangchar) ? x[1] : '\0';
1007 hashchar = (hatchar) ? x[2] : '\0';
1008 free(x);
1009 }
1010}
1011
1012char *histcharsgetfn(pm) /**/
1013Param pm;
1014{
1015static char buf[4];
1016
1017 buf[0] = bangchar;
1018 buf[1] = hatchar;
1019 buf[2] = hashchar;
1020 buf[3] = '\0';
1021 return buf;
1022}
1023
1024char *homegetfn(pm) /**/
1025Param pm;
1026{
1027 return home;
1028}
1029
1030void homesetfn(pm,x) /**/
1031Param pm;char *x;
1032{
1033 free(home);
1034 if (isset(CHASELINKS) && (home = xsymlink(x))) free(x);
1035 else home = x;
1036}
1037
1038char *wordcharsgetfn(pm) /**/
1039Param pm;
1040{
1041 return wordchars;
1042}
1043
1044void wordcharssetfn(pm,x) /**/
1045Param pm;char *x;
1046{
1047 free(wordchars);
1048 if (x) wordchars = x;
1049 else wordchars = ztrdup(DEFWORDCHARS);
1050 inittyptab();
1051}
1052
1053char *underscoregetfn(pm) /**/
1054Param pm;
1055{
1056char *s,*t;
1057
1058 if (!(s = qgetevent(curhist-1)))
1059 return "";
1060 for (t = s+strlen(s); t > s; t--)
1061 if (*t == HISTSPACE)
1062 break;
1063 if (t != s)
1064 t++;
1065 return t;
1066}
1067
1068char *termgetfn(pm) /**/
1069Param pm;
1070{
1071 return term;
1072}
1073
1074void termsetfn(pm,x) /**/
1075Param pm;char *x;
1076{
1077 if (term) free(term);
1078 term = x;
1079 if (!interact || unset(USEZLE))
1080 return;
1081 if (tgetent(termbuf,term) != 1)
1082 {
1083 zerr("can't find termcap info for %s",term,0);
1084 errflag = 0;
1085 termok = 0;
1086 }
1087 else
1088 {
1089 char tbuf[1024],*pp;
1090 int t0;
1091
1092 termok = 1;
1093 for (t0 = 0; t0 != TC_COUNT; t0++)
1094 {
1095 pp = tbuf;
1096 if (tcstr[t0])
1097 free(tcstr[t0]);
1098 if (!tgetstr(tccapnams[t0],&pp))
1099 tcstr[t0] = NULL, tclen[t0] = 0;
1100 else
1101 {
1102 tcstr[t0] = zalloc(tclen[t0] = pp-tbuf);
1103 memcpy(tcstr[t0],tbuf,tclen[t0]);
1104 }
1105 }
1106
1107/* if there's no termcap entry for cursor left, use \b. */
1108
1109 if (!tccan(TCLEFT))
1110 {
1111 tcstr[TCLEFT] = ztrdup("\b");
1112 tclen[TCLEFT] = 1;
1113 }
1114
1115/* if there's no termcap entry for clear, use ^L. */
1116
1117 if (!tccan(TCCLEARSCREEN))
1118 {
1119 tcstr[TCCLEARSCREEN] = ztrdup("\14");
1120 tclen[TCCLEARSCREEN] = 1;
1121 }
1122
1123/* if the termcap entry for down is \n, don't use it. */
1124
1125 if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n')
1126 {
1127 tclen[TCDOWN] = 0;
1128 free(tcstr[TCDOWN]);
1129 tcstr[TCDOWN] = NULL;
1130 }
1131
1132/* if there's no termcap entry for cursor up, forget it.
1133 Use single line mode. */
1134
1135 if (!tccan(TCUP))
1136 termok = 0;
1137 }
1138}
1139
1140void setparams() /**/
1141{
1142char **envp,**envp2,**envp3,*str;
1143char buf[50];
1144struct param *pm;
1145int ct;
1146
1147 noerrs = 1;
1148 for (envp = environ, ct = 2; *envp; envp++,ct++);
1149 envp = environ;
1150 envp2 = envp3 = (char **) zalloc(sizeof(char *)*ct);
1151 for (; *envp; envp++)
1152 *envp2++ = ztrdup(*envp);
1153 *envp2 = NULL;
1154 envp = environ;
1155 environ = envp2 = envp3;
1156 for (; *envp; envp++,envp2++) {
1157 for (str = *envp; *str && *str != '='; str++);
1158 if (*str == '=') {
1159 char *iname;
1160
1161 *str = '\0';
1162 if (isident(*envp))
1163 pm = setsparam(iname = *envp,ztrdup(str+1));
1164 if (pm) {
1165 pm->flags |= PMFLAG_x;
1166 pm->env = *envp2;
1167 if (pm->flags & PMFLAG_SPECIAL)
1168 pm->env = replenv(pm->env,getsparam(iname));
1169 }
1170 *str = '=';
1171 }
1172 }
1173 pm = gethnode("HOME",paramtab);
1174 if (!(pm->flags & PMFLAG_x)) {
1175 pm->flags |= PMFLAG_x;
1176 pm->env = addenv("HOME",home);
1177 }
1178 pm = gethnode("PWD",paramtab);
1179 if (!(pm->flags & PMFLAG_x)) {
1180 pm->flags |= PMFLAG_x;
1181 pm->env = addenv("PWD",pwd);
1182 }
1183 pm = gethnode("LOGNAME",paramtab);
1184 if (!(pm->flags & PMFLAG_x)) {
1185 pm->flags |= PMFLAG_x;
1186 pm->env = addenv("LOGNAME",logname);
1187 }
1188 pm = gethnode("SHLVL",paramtab);
1189 if (!(pm->flags & PMFLAG_x))
1190 pm->flags |= PMFLAG_x;
1191 sprintf(buf,"%d",++shlvl);
1192 pm->env = addenv("SHLVL",buf);
1193 noerrs = 0;
1194}
1195
1196char *mkenvstr(x,y) /**/
1197char *x;char *y;
1198{
1199char *z;
1200int xl = strlen(x),yl = strlen(y);
1201
1202 z = zalloc(xl+yl+2);
1203 strcpy(z,x);
1204 z[xl] = '=';
1205 strcpy(z+xl+1,y);
1206 z[xl+yl+1] = '\0';
1207 return z;
1208}
1209
1210void arrfixenv(s,t) /**/
1211char *s;char **t;
1212{
1213char **ep;
1214int sl = strlen(s);
1215
1216 for (ep = environ; *ep; ep++)
1217 if (!strncmp(*ep,s,sl) && (*ep)[sl] == '=') {
1218 char *u = colonjoin(t);
1219 replenv(*ep,u);
1220 break;
1221 }
1222}
1223
1224char *replenv(e,value) /**/
1225char *e;char *value;
1226{
1227char **ep;
1228
1229 for (ep = environ; *ep; ep++)
1230 if (*ep == e)
1231 {
1232 char *s = e;
1233
1234 while (*s++ != '=');
1235 *s = '\0';
1236 *ep = zalloc(strlen(e)+strlen(value)+2);
1237 strcpy(*ep,e);
1238 strcat(*ep,value);
1239 free(e);
1240 return *ep;
1241 }
1242 return NULL;
1243}
1244
1245char *addenv(name,value) /**/
1246char *name;char *value;
1247{
1248char **ep,**ep2,**ep3;
1249int envct;
1250
1251 for (ep = environ; *ep; ep++)
1252 {
1253 char *s = *ep,*t = name;
1254
1255 while (*s && *s == *t) s++,t++;
1256 if (*s == '=' && !*t)
1257 {
1258 free(*ep);
1259 return *ep = mkenvstr(name,value);
1260 }
1261 }
1262 envct = arrlen(environ);
1263 ep = ep2 = (char **) zalloc((sizeof (char *))*(envct+3));
1264 for (ep3 = environ; *ep2 = *ep3; ep3++,ep2++);
1265 *ep2 = mkenvstr(name,value);
1266 ep2[1] = NULL;
1267 free(environ);
1268 environ = ep;
1269 return *ep2;
1270}
1271
1272void delenv(x) /**/
1273char *x;
1274{
1275char **ep;
1276
1277 ep = environ;
1278 for (; *ep; ep++)
1279 if (*ep == x)
1280 break;
1281 if (*ep)
1282 for (; ep[0] = ep[1]; ep++);
1283}
1284
1285void convbase(s,v,base) /**/
1286char *s;long v;int base;
1287{
1288int digs = 0;
1289long x;
1290
1291 if (base <= 1)
1292 base = 10;
1293 x = v;
1294 if (x < 0)
1295 {
1296 x = -x;
1297 digs++;
1298 }
1299 for (; x; digs++)
1300 x /= base;
1301 if (!digs)
1302 digs = 1;
1303 s[digs--] = '\0';
1304 x = (v < 0) ? -v : v;
1305 while (digs >= 0)
1306 {
1307 int dig = x%base;
1308 s[digs--] = (dig < 10) ? '0'+dig : dig-10+'A';
1309 x /= base;
1310 }
1311 if (v < 0)
1312 s[0] = '-';
1313}
1314
1315