Commit | Line | Data |
---|---|---|
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 | ||
26 | static Param argvparam; | |
27 | ||
28 | struct 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 | ||
44 | void setupparams() /**/ | |
45 | { | |
46 | static 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 | }; | |
167 | struct iparam *ip; | |
168 | ||
169 | for (ip = pinit; ip->nam; ip++) addhperm(ip->nam,ip,paramtab,NULL); | |
170 | argvparam = gethnode("argv",paramtab); | |
171 | } | |
172 | ||
173 | static int unsetflag; | |
174 | ||
175 | struct param *createparam(name,value,flags) /**/ | |
176 | char *name;vptr value;int flags; | |
177 | { | |
178 | struct param *pm; | |
179 | char 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 | ||
206 | int isident(s) /**/ | |
207 | char *s; | |
208 | { | |
209 | char *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 | ||
227 | Value getvalue(pptr,bracks) /**/ | |
228 | char **pptr;int bracks; | |
229 | { | |
230 | char *s = *pptr,*t = *pptr; | |
231 | char sav; | |
232 | Value 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 | ||
307 | char *getstrvalue(v) /**/ | |
308 | Value v; | |
309 | { | |
310 | char *s,**ss; | |
311 | static 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 | ||
336 | char **getarrvalue(v) /**/ | |
337 | Value v; | |
338 | { | |
339 | char **s; | |
340 | static 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 | ||
357 | long getintvalue(v) /**/ | |
358 | Value v; | |
359 | { | |
360 | char **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 | ||
375 | void setstrvalue(v,val) /**/ | |
376 | Value v;char *val; | |
377 | { | |
378 | char *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 | ||
450 | void setintvalue(v,val) /**/ | |
451 | Value v;long val; | |
452 | { | |
453 | char 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 | ||
478 | void setintenv(s,val) /**/ | |
479 | char *s; long val; | |
480 | { | |
481 | Param pm; | |
482 | char 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 | ||
490 | void setarrvalue(v,val) /**/ | |
491 | Value 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 | ||
503 | char *getsparamval(s,l) /**/ | |
504 | char *s;int l; | |
505 | { | |
506 | char sav,*t = s; | |
507 | Value 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 | ||
518 | long getiparam(s) /**/ | |
519 | char *s; | |
520 | { | |
521 | Value v; | |
522 | ||
523 | if (!(v = getvalue(&s,0))) | |
524 | return 0; | |
525 | return getintvalue(v); | |
526 | } | |
527 | ||
528 | char *getsparam(s) /**/ | |
529 | char *s; | |
530 | { | |
531 | Value v; | |
532 | ||
533 | if (!(v = getvalue(&s,0))) | |
534 | return NULL; | |
535 | return getstrvalue(v); | |
536 | } | |
537 | ||
538 | char **getaparam(s) /**/ | |
539 | char *s; | |
540 | { | |
541 | Value v; | |
542 | ||
543 | if (!(v = getvalue(&s,0))) return NULL; | |
544 | return getarrvalue(v); | |
545 | } | |
546 | ||
547 | Param setsparam(s,val) /**/ | |
548 | char *s;char *val; | |
549 | { | |
550 | Value v; | |
551 | char *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 | ||
569 | Param setaparam(s,val) /**/ | |
570 | char *s;char **val; | |
571 | { | |
572 | Value v; | |
573 | char *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 | ||
591 | Param setiparam(s,val) /**/ | |
592 | char *s;long val; | |
593 | { | |
594 | Value v; | |
595 | char *t = s; | |
596 | Param 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 | ||
613 | void unsetparam(s) /**/ | |
614 | char *s; | |
615 | { | |
616 | Param 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 | ||
644 | void intsetfn(pm,x) /**/ | |
645 | Param pm;long x; | |
646 | { | |
647 | pm->u.val = x; | |
648 | } | |
649 | ||
650 | long intgetfn(pm) /**/ | |
651 | Param pm; | |
652 | { | |
653 | return pm->u.val; | |
654 | } | |
655 | ||
656 | void strsetfn(pm,x) /**/ | |
657 | Param 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 | ||
667 | char *strgetfn(pm) /**/ | |
668 | Param pm; | |
669 | { | |
670 | return pm->u.str; | |
671 | } | |
672 | ||
673 | void nullsetfn(pm,x) /**/ | |
674 | Param pm; char *x; | |
675 | { | |
676 | free(x); | |
677 | } | |
678 | ||
679 | void arrsetfn(pm,x) /**/ | |
680 | Param pm;char **x; | |
681 | { | |
682 | int 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 | ||
694 | char **arrgetfn(pm) /**/ | |
695 | Param pm; | |
696 | { | |
697 | return pm->u.arr; | |
698 | } | |
699 | ||
700 | void intvarsetfn(pm,x) /**/ | |
701 | Param pm;long x; | |
702 | { | |
703 | *((long *) pm->data) = x; | |
704 | } | |
705 | ||
706 | long intvargetfn(pm) /**/ | |
707 | Param pm; | |
708 | { | |
709 | return *((long *) pm->data); | |
710 | } | |
711 | ||
712 | void strvarsetfn(pm,x) /**/ | |
713 | Param pm;char *x; | |
714 | { | |
715 | char **q = ((char **) pm->data); | |
716 | ||
717 | if (*q) free(*q); | |
718 | *q = x; | |
719 | } | |
720 | ||
721 | void strvarnonullsetfn(pm,x) /**/ | |
722 | Param pm;char *x; | |
723 | { | |
724 | char **q = ((char **) pm->data); | |
725 | ||
726 | if (*q) free(*q); | |
727 | *q = (x) ? x : ztrdup(""); | |
728 | } | |
729 | ||
730 | char *strvargetfn(pm) /**/ | |
731 | Param pm; | |
732 | { | |
733 | char *s; | |
734 | ||
735 | s = *((char **) pm->data); | |
736 | if (!s) return ""; | |
737 | return s; | |
738 | } | |
739 | ||
740 | char *strconstgetfn(pm) /**/ | |
741 | Param pm; | |
742 | { | |
743 | return (char *) pm->data; | |
744 | } | |
745 | ||
746 | void colonarrsetfn(pm,x) /**/ | |
747 | Param pm;char *x; | |
748 | { | |
749 | char **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 | ||
778 | char *colonarrgetfn(pm) /**/ | |
779 | Param pm; | |
780 | { | |
781 | if ((char **) pm->data) | |
782 | return colonjoin(*(char ***) pm->data); | |
783 | else | |
784 | return colonjoin(path); | |
785 | } | |
786 | ||
787 | char **arrvargetfn(pm) /**/ | |
788 | Param pm; | |
789 | { | |
790 | return *((char ***) pm->data); | |
791 | } | |
792 | ||
793 | void arrvarsetfn(pm,x) /**/ | |
794 | Param 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 | ||
803 | char **pathgetfn(pm) /**/ | |
804 | Param pm; | |
805 | { | |
806 | return path; | |
807 | } | |
808 | ||
809 | void pathsetfn(pm,x) /**/ | |
810 | Param pm;char **x; | |
811 | { | |
812 | if (path != x) freearray(path); | |
813 | path = x; | |
814 | newcmdnamtab(); | |
815 | arrfixenv("PATH",x); | |
816 | } | |
817 | ||
818 | void hostcmdssetfn(pm,x) /**/ | |
819 | Param pm;char **x; | |
820 | { | |
821 | compctl_process(x,CC_HOSTS|CC_FILES,NULL); | |
822 | freearray(x); | |
823 | } | |
824 | ||
825 | void optcmdssetfn(pm,x) /**/ | |
826 | Param pm;char **x; | |
827 | { | |
828 | compctl_process(x,CC_OPTIONS,NULL); | |
829 | freearray(x); | |
830 | } | |
831 | ||
832 | void bindcmdssetfn(pm,x) /**/ | |
833 | Param pm;char **x; | |
834 | { | |
835 | compctl_process(x,CC_BINDINGS,NULL); | |
836 | freearray(x); | |
837 | } | |
838 | ||
839 | void varcmdssetfn(pm,x) /**/ | |
840 | Param pm;char **x; | |
841 | { | |
842 | compctl_process(x,CC_VARS,NULL); | |
843 | freearray(x); | |
844 | } | |
845 | ||
846 | char **nullgetfn(pm) /**/ | |
847 | Param pm; | |
848 | { | |
849 | static char *nl = NULL; return &nl; | |
850 | } | |
851 | ||
852 | void unsettablesetfn(pm,x) /**/ | |
853 | Param pm;char *x; | |
854 | { ; } | |
855 | ||
856 | long poundgetfn(pm) /**/ | |
857 | Param pm; | |
858 | { | |
859 | return arrlen(pparams); | |
860 | } | |
861 | ||
862 | long randomgetfn(pm) /**/ | |
863 | Param pm; | |
864 | { | |
865 | return rand() & 0x7fff; | |
866 | } | |
867 | ||
868 | void randomsetfn(pm,v) /**/ | |
869 | Param pm;long v; | |
870 | { | |
871 | srand((unsigned int) v); | |
872 | } | |
873 | ||
874 | long secondsgetfn(pm) /**/ | |
875 | Param pm; | |
876 | { | |
877 | return time(NULL)-shtimer; | |
878 | } | |
879 | ||
880 | void secondssetfn(pm,x) /**/ | |
881 | Param pm;long x; | |
882 | { | |
883 | shtimer = time(NULL)-x; | |
884 | } | |
885 | ||
886 | long uidgetfn(pm) /**/ | |
887 | Param pm; | |
888 | { | |
889 | return getuid(); | |
890 | } | |
891 | ||
892 | long gidgetfn(pm) /**/ | |
893 | Param pm; | |
894 | { | |
895 | return getegid(); | |
896 | } | |
897 | ||
898 | char *usernamegetfn(pm) /**/ | |
899 | Param pm; | |
900 | { | |
901 | struct passwd *pwd; | |
902 | ||
903 | pwd = getpwuid(getuid()); | |
904 | return pwd->pw_name; | |
905 | } | |
906 | ||
907 | char *hostgetfn(pm) /**/ | |
908 | Param pm; | |
909 | { | |
910 | static char hostnam[65]; | |
911 | static 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 | ||
922 | char *ifsgetfn(pm) /**/ | |
923 | Param pm; | |
924 | { | |
925 | return ifs; | |
926 | } | |
927 | ||
928 | void ifssetfn(pm,x) /**/ | |
929 | Param pm;char *x; | |
930 | { | |
931 | if (x) { free(ifs); ifs = x; } | |
932 | inittyptab(); | |
933 | } | |
934 | ||
935 | void histsizesetfn(pm,v) /**/ | |
936 | Param pm;long v; | |
937 | { | |
938 | if ((histsiz = v) <= 2) histsiz = 2; | |
939 | resizehistents(); | |
940 | } | |
941 | ||
942 | long histsizegetfn(pm) /**/ | |
943 | Param pm; | |
944 | { | |
945 | return histsiz; | |
946 | } | |
947 | ||
948 | void lithistsizesetfn(pm,v) /**/ | |
949 | Param pm;long v; | |
950 | { | |
951 | if ((lithistsiz = v) <= 2) lithistsiz = 2; | |
952 | resizehistents(); | |
953 | } | |
954 | ||
955 | long lithistsizegetfn(pm) /**/ | |
956 | Param pm; | |
957 | { | |
958 | return lithistsiz; | |
959 | } | |
960 | ||
961 | void mailchecksetfn(pm,x) /**/ | |
962 | Param pm;long x; | |
963 | { | |
964 | mailcheck = (unsetflag) ? 600 : x; | |
965 | } | |
966 | ||
967 | void pathasetfn(pm,x) /**/ | |
968 | Param pm;char **x; | |
969 | { | |
970 | freearray(path); | |
971 | path = x; | |
972 | newcmdnamtab(); | |
973 | } | |
974 | ||
975 | char **pathagetfn(pm) /**/ | |
976 | Param pm; | |
977 | { | |
978 | return path; | |
979 | } | |
980 | ||
981 | long errnogetfn(pm) /**/ | |
982 | Param pm; | |
983 | { | |
984 | return errno; | |
985 | } | |
986 | ||
987 | char *dashgetfn(pm) /**/ | |
988 | Param pm; | |
989 | { | |
990 | static char buf[100]; | |
991 | char *val = buf; | |
992 | int 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 | ||
1001 | void histcharssetfn(pm,x) /**/ | |
1002 | Param 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 | ||
1012 | char *histcharsgetfn(pm) /**/ | |
1013 | Param pm; | |
1014 | { | |
1015 | static 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 | ||
1024 | char *homegetfn(pm) /**/ | |
1025 | Param pm; | |
1026 | { | |
1027 | return home; | |
1028 | } | |
1029 | ||
1030 | void homesetfn(pm,x) /**/ | |
1031 | Param pm;char *x; | |
1032 | { | |
1033 | free(home); | |
1034 | if (isset(CHASELINKS) && (home = xsymlink(x))) free(x); | |
1035 | else home = x; | |
1036 | } | |
1037 | ||
1038 | char *wordcharsgetfn(pm) /**/ | |
1039 | Param pm; | |
1040 | { | |
1041 | return wordchars; | |
1042 | } | |
1043 | ||
1044 | void wordcharssetfn(pm,x) /**/ | |
1045 | Param pm;char *x; | |
1046 | { | |
1047 | free(wordchars); | |
1048 | if (x) wordchars = x; | |
1049 | else wordchars = ztrdup(DEFWORDCHARS); | |
1050 | inittyptab(); | |
1051 | } | |
1052 | ||
1053 | char *underscoregetfn(pm) /**/ | |
1054 | Param pm; | |
1055 | { | |
1056 | char *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 | ||
1068 | char *termgetfn(pm) /**/ | |
1069 | Param pm; | |
1070 | { | |
1071 | return term; | |
1072 | } | |
1073 | ||
1074 | void termsetfn(pm,x) /**/ | |
1075 | Param 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 | ||
1140 | void setparams() /**/ | |
1141 | { | |
1142 | char **envp,**envp2,**envp3,*str; | |
1143 | char buf[50]; | |
1144 | struct param *pm; | |
1145 | int 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 | ||
1196 | char *mkenvstr(x,y) /**/ | |
1197 | char *x;char *y; | |
1198 | { | |
1199 | char *z; | |
1200 | int 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 | ||
1210 | void arrfixenv(s,t) /**/ | |
1211 | char *s;char **t; | |
1212 | { | |
1213 | char **ep; | |
1214 | int 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 | ||
1224 | char *replenv(e,value) /**/ | |
1225 | char *e;char *value; | |
1226 | { | |
1227 | char **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 | ||
1245 | char *addenv(name,value) /**/ | |
1246 | char *name;char *value; | |
1247 | { | |
1248 | char **ep,**ep2,**ep3; | |
1249 | int 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 | ||
1272 | void delenv(x) /**/ | |
1273 | char *x; | |
1274 | { | |
1275 | char **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 | ||
1285 | void convbase(s,v,base) /**/ | |
1286 | char *s;long v;int base; | |
1287 | { | |
1288 | int digs = 0; | |
1289 | long 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 |