void mklocal(const char *name, int flags) { struct localvar *lvp; struct var **vpp; struct var *vp; INTOFF; lvp = ckmalloc(sizeof (struct localvar)); if (name[0] == '-' && name[1] == '\0') { char *p; p = ckmalloc(sizeof_optlist); lvp->text = memcpy(p, optlist, sizeof_optlist); vp = NULL; } else { vp = find_var(name, &vpp, NULL); if (vp == NULL) { if (strchr(name, '=')) setvareq(savestr(name), VSTRFIXED|flags); else setvar(name, NULL, VSTRFIXED|flags); vp = *vpp; /* the new variable */ lvp->text = NULL; lvp->flags = VUNSET; } else { lvp->text = vp->text; lvp->flags = vp->flags; vp->flags |= VSTRFIXED|VTEXTFIXED; if (name[vp->name_len] == '=') setvareq(savestr(name), flags); } } lvp->vp = vp; lvp->next = localvars; localvars = lvp; INTON; }
/** * usbd_alloc_urb - allocate an URB appropriate for specified endpoint * @device: device instance * @function_instance: device instance * @endpoint: endpoint * @length: size of transfer buffer to allocate * * Allocate an urb structure. The usb device urb structure is used to * contain all data associated with a transfer, including a setup packet for * control transfers. * * NOTE: endpoint_address MUST contain a direction flag. */ struct urb *usbd_alloc_urb (struct usb_device_instance *device, struct usb_function_instance *function_instance, __u8 endpoint_address, int length) { int i; for (i = 0; i < device->bus->driver->max_endpoints; i++) { struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + i; dbg_urbmem (2, "i=%d epa=%d want %d", i, endpoint->endpoint_address, endpoint_address); if (endpoint->endpoint_address == endpoint_address) { struct urb *urb; dbg_urbmem (2, "[%d]: endpoint: %p %02x length: %d", i, endpoint, endpoint->endpoint_address, length); if (!(urb = ckmalloc (sizeof (struct urb), GFP_ATOMIC))) { dbg_urbmem (0, "ckmalloc(%u,GFP_ATOMIC) failed", sizeof (struct urb)); return NULL; } urb->endpoint = endpoint; urb->device = device; urb->function_instance = function_instance; urb_link_init (&urb->link); if (length) { if (usbd_alloc_urb_data (urb, length)) { dbg_urbmem (0, "usbd_alloc_urb_data(%u,GFP_ATOMIC) failed", length); kfree (urb); return NULL; } } else { urb->buffer_length = urb->actual_length = 0; } dbg_urbmem(1, "[%d] urb: %p len: %d", endpoint_address, urb, length); return urb; } } dbg_urbmem (0, "can't find endpoint #%02x!", endpoint_address); for (i = 0; i < device->bus->driver->max_endpoints; i++) { struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + i; dbg_urbmem (0, "i=%d epa=%d want %d", i, endpoint->endpoint_address, endpoint_address); if (endpoint->endpoint_address == endpoint_address) { dbg_urbmem (0, "found it, but too late"); break; } } return NULL; }
STATIC void expandmeta(shinstance *psh, struct strlist *str, int flag) { char *p; struct strlist **savelastp; struct strlist *sp; char c; /* TODO - EXP_REDIR */ while (str) { if (fflag(psh)) goto nometa; p = str->text; for (;;) { /* fast check for meta chars */ if ((c = *p++) == '\0') goto nometa; if (c == '*' || c == '?' || c == '[' || c == '!') break; } savelastp = psh->exparg.lastp; INTOFF; if (psh->expdir == NULL) { size_t i = strlen(str->text); psh->expdir = ckmalloc(psh, i < 2048 ? 2048 : i); /* XXX */ } expmeta(psh, psh->expdir, str->text); ckfree(psh, psh->expdir); psh->expdir = NULL; INTON; if (psh->exparg.lastp == savelastp) { /* * no matches */ nometa: *psh->exparg.lastp = str; rmescapes(psh, str->text); psh->exparg.lastp = &str->next; } else { *psh->exparg.lastp = NULL; *savelastp = sp = expsort(*savelastp); while (sp->next != NULL) sp = sp->next; psh->exparg.lastp = &sp->next; } str = str->next; } }
static void pushfile(void) { struct parsefile *pf; parsefile->nleft = parsenleft; parsefile->lleft = parselleft; parsefile->nextc = parsenextc; parsefile->linno = plinno; pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); pf->prev = parsefile; pf->fd = -1; pf->strpush = NULL; pf->basestrpush.prev = NULL; parsefile = pf; }
int showvars(shinstance *psh, const char *name, int flag, int show_value) { struct var **vpp; struct var *vp; const char *p; static struct var **list; /* static in case we are interrupted */ static int list_len; int count = 0; if (!list) { list_len = 32; list = ckmalloc(psh, list_len * sizeof(*list)); } for (vpp = psh->vartab ; vpp < psh->vartab + VTABSIZE ; vpp++) { for (vp = *vpp ; vp ; vp = vp->next) { if (flag && !(vp->flags & flag)) continue; if (vp->flags & VUNSET && !(show_value & 2)) continue; if (count >= list_len) { list = ckrealloc(psh, list, (list_len << 1) * sizeof(*list)); list_len <<= 1; } list[count++] = vp; } } qsort(list, count, sizeof(*list), sort_var); for (vpp = list; count--; vpp++) { vp = *vpp; if (name) out1fmt(psh, "%s ", name); for (p = vp->text ; *p != '=' ; p++) out1c(psh, *p); if (!(vp->flags & VUNSET) && show_value) { out1fmt(psh, "="); print_quoted(psh, ++p); } out1c(psh, '\n'); } return 0; }
STATIC void recordregion(int start, int end, int nulonly) { struct ifsregion *ifsp; if (ifslastp == NULL) { ifsp = &ifsfirst; } else { ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); ifslastp->next = ifsp; } ifslastp = ifsp; ifslastp->next = NULL; ifslastp->begoff = start; ifslastp->endoff = end; ifslastp->nulonly = nulonly; }
void setvareq(char *s, int flags) { struct var *vp, **vpp; int nlen; if (aflag) flags |= VEXPORT; vp = find_var(s, &vpp, &nlen); if (vp != NULL) { if (vp->flags & VREADONLY) error("%.*s: is read only", vp->name_len, s); if (flags & VNOSET) return; INTOFF; if (vp->func && (flags & VNOFUNC) == 0) (*vp->func)(s + vp->name_len + 1); if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) ckfree(vp->text); vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); vp->flags |= flags & ~VNOFUNC; vp->text = s; /* * We could roll this to a function, to handle it as * a regular variable function callback, but why bother? */ if (vp == &vmpath || (vp == &vmail && ! mpathset())) chkmail(1); INTON; return; } /* not found */ if (flags & VNOSET) return; vp = ckmalloc(sizeof (*vp)); vp->flags = flags & ~VNOFUNC; vp->text = s; vp->name_len = nlen; vp->next = *vpp; vp->func = NULL; *vpp = vp; }
static void printaliases(void) { int i, j; struct alias **sorted, *ap; sorted = ckmalloc(aliases * sizeof(*sorted)); j = 0; for (i = 0; i < ATABSIZE; i++) for (ap = atab[i]; ap; ap = ap->next) if (*ap->name != '\0') sorted[j++] = ap; qsort(sorted, aliases, sizeof(*sorted), comparealiases); for (i = 0; i < aliases; i++) printalias(sorted[i]); ckfree(sorted); }
static Pipe mkPipe() { Pipe p; Cmd c; c = mkCmd(Tnil); // at least one command // ignore NULL cmds--generated by empty line or error if ( c == NULL || c == &Empty ) return NULL; // allocate the pipe structure p = ckmalloc(sizeof(*p)); p->type = Pout; // set type to Pout until we know differently p->head = c; while ( PipeToken(LA) ) { if ( LA == TpipeErr ) p->type = PoutErr; // reset type if ( c->out != Tnil ) { printf("Ambiguous output redirect.\n"); // skip to end of command do { Next(); } while ( !EndOfInput(LA) ); freeCmd(c); return NULL; } Next(); c->next = mkCmd(p->type == Pout ? Tpipe : TpipeErr); if ( c->next == NULL || c->next == &Empty ) { if ( c->next == &Empty ) printf("Invalid null command.\n"); while ( !EndOfInput(LA) ) Next(); return NULL; } c = c->next; } // read next pipe on the line p->next = NULL; while ( !EndOfInput(LA) ) p->next = mkPipe(); return p; } /*---------- End of mkPipe ------------------------------------------------*/
/** * usbd_alloc_urb_data - allocate urb data buffer * @urb: pointer to urb * @len: size of buffer to allocate * * Allocate a data buffer for the specified urb structure. */ int usbd_alloc_urb_data (struct urb *urb, int len) { len += 2; urb->buffer_length = len; urb->actual_length = 0; if (len == 0) { dbg_urbmem (0, "len == zero"); return 0; } if (urb->endpoint && urb->endpoint->endpoint_address && urb->function_instance && urb->function_instance->function_driver->ops->alloc_urb_data) { dbg_urbmem (0, "urb->function->ops used"); return urb->function_instance->function_driver->ops->alloc_urb_data (urb, len); } return !(urb->buffer = ckmalloc (len, GFP_ATOMIC)); }
STATIC void setalias(char *name, char *val) { struct alias *ap, **app; (void) unalias(name); /* old one (if any) is now gone */ app = hashalias(name); INTOFF; ap = ckmalloc(sizeof (struct alias)); ap->name = savestr(name); ap->flag = 0; ap->val = savestr(val); ap->next = *app; *app = ap; INTON; }
void setparam(char **argv) { char **newparam; char **ap; int nparam; for (nparam = 0 ; argv[nparam] ; nparam++); ap = newparam = ckmalloc((nparam + 1) * sizeof *ap); while (*argv) { *ap++ = savestr(*argv++); } *ap = NULL; freeparam(&shellparam); shellparam.malloc = 1; shellparam.nparam = nparam; shellparam.p = newparam; shellparam.optnext = NULL; }
void setvar(shinstance *psh, const char *name, const char *val, int flags) { const char *p; const char *q; char *d; size_t len; int namelen; char *nameeq; int isbad; isbad = 0; p = name; if (! is_name(*p)) isbad = 1; p++; for (;;) { if (! is_in_name(*p)) { if (*p == '\0' || *p == '=') break; isbad = 1; } p++; } namelen = (int)(p - name); if (isbad) error(psh, "%.*s: bad variable name", namelen, name); len = namelen + 2; /* 2 is space for '=' and '\0' */ if (val == NULL) { flags |= VUNSET; } else { len += strlen(val); } d = nameeq = ckmalloc(psh, len); q = name; while (--namelen >= 0) *d++ = *q++; *d++ = '='; *d = '\0'; if (val) scopy(val, d); setvareq(psh, nameeq, flags); }
static void stnewblock(int nbytes) { struct stack_block *sp; int allocsize; if (nbytes < MINSIZE) nbytes = MINSIZE; allocsize = ALIGN(sizeof(struct stack_block)) + ALIGN(nbytes); INTOFF; sp = ckmalloc(allocsize); sp->prev = stackp; stacknxt = SPACE(sp); stacknleft = allocsize - (stacknxt - (char*)sp); stackp = sp; INTON; }
static void setparam(int argc, char **argv) { char **newparam; char **ap; ap = newparam = ckmalloc((argc + 1) * sizeof *ap); while (*argv) { *ap++ = savestr(*argv++); } *ap = NULL; freeparam(&shellparam); shellparam.malloc = 1; shellparam.nparam = argc; shellparam.p = newparam; shellparam.optp = NULL; shellparam.reset = 1; shellparam.optnext = NULL; }
void setvar(char *name, char *val, int flags) { char *p, *q; int len; int namelen; char *nameeq; int isbad; isbad = 0; p = name; if (! is_name(*p)) isbad = 1; p++; for (;;) { if (! is_in_name(*p)) { if (*p == '\0' || *p == '=') break; isbad = 1; } p++; } namelen = p - name; if (isbad) error("%.*s: bad variable name", namelen, name); len = namelen + 2; /* 2 is space for '=' and '\0' */ if (val == NULL) { flags |= VUNSET; } else { len += strlen(val); } p = nameeq = ckmalloc(len); q = name; while (--namelen >= 0) *p++ = *q++; *p++ = '='; *p = '\0'; if (val) scopy(val, p); setvareq(nameeq, flags); }
static const char * syspath(void) { static char *sys_path = NULL; static int mib[] = {CTL_USER, USER_CS_PATH}; static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; size_t len; if (sys_path == NULL) { if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && (sys_path = ckmalloc(len + 5)) != NULL && sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { memcpy(sys_path, "PATH=", 5); } else { ckfree(sys_path); /* something to keep things happy */ sys_path = def_path; } } return sys_path; }
static void reprocess(int startloc, int flag, int subtype, int quoted, struct worddest *dst) { static char *buf = NULL; static size_t buflen = 0; char *startp; size_t len, zpos, zlen; startp = stackblock() + startloc; len = expdest - startp; if (len >= SIZE_MAX / 2) abort(); INTOFF; if (len >= buflen) { ckfree(buf); buf = NULL; } if (buflen < 128) buflen = 128; while (len >= buflen) buflen <<= 1; if (buf == NULL) buf = ckmalloc(buflen); INTON; memcpy(buf, startp, len); buf[len] = '\0'; STADJUST(-len, expdest); for (zpos = 0;;) { zlen = strlen(buf + zpos); strtodest(buf + zpos, flag, subtype, quoted, dst); zpos += zlen + 1; if (zpos == len + 1) break; if (flag & EXP_SPLIT && (quoted || (zlen > 0 && zpos < len))) NEXTWORD('\0', flag, expdest, dst); } }
static void recordregion(int start, int end, int inquotes) { struct ifsregion *ifsp; if (ifslastp == NULL) { ifsp = &ifsfirst; } else { if (ifslastp->endoff == start && ifslastp->inquotes == inquotes) { /* extend previous area */ ifslastp->endoff = end; return; } ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); ifslastp->next = ifsp; } ifslastp = ifsp; ifslastp->next = NULL; ifslastp->begoff = start; ifslastp->endoff = end; ifslastp->inquotes = inquotes; }
STATIC void recordregion(shinstance *psh, int start, int end, int inquotes) { struct ifsregion *ifsp; if (psh->ifslastp == NULL) { ifsp = &psh->ifsfirst; } else { if (psh->ifslastp->endoff == start && psh->ifslastp->inquotes == inquotes) { /* extend previous area */ psh->ifslastp->endoff = end; return; } ifsp = (struct ifsregion *)ckmalloc(psh, sizeof (struct ifsregion)); psh->ifslastp->next = ifsp; } psh->ifslastp = ifsp; psh->ifslastp->next = NULL; psh->ifslastp->begoff = start; psh->ifslastp->endoff = end; psh->ifslastp->inquotes = inquotes; }
/* * Push a string back onto the input at this current parsefile level. * We handle aliases this way. */ void pushstring(char *s, int len, void *ap) { struct strpush *sp; INTOFF; /*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/ if (parsefile->strpush) { sp = ckmalloc(sizeof (struct strpush)); sp->prev = parsefile->strpush; parsefile->strpush = sp; } else sp = parsefile->strpush = &(parsefile->basestrpush); sp->prevstring = parsenextc; sp->prevnleft = parsenleft; sp->prevlleft = parselleft; sp->ap = (struct alias *)ap; if (ap) ((struct alias *)ap)->flag |= ALIASINUSE; parsenextc = s; parsenleft = len; INTON; }
void emptyoutbuf(struct output *dest) { int offset; if (dest->buf == NULL) { INTOFF; dest->buf = ckmalloc(dest->bufsize); dest->nextc = dest->buf; dest->nleft = dest->bufsize; INTON; } else if (dest->fd == MEM_OUT) { offset = dest->bufsize; INTOFF; dest->bufsize <<= 1; dest->buf = ckrealloc(dest->buf, dest->bufsize); dest->nleft = dest->bufsize - offset; dest->nextc = dest->buf + offset; INTON; } else { flushout(dest); } dest->nleft--; }
void pushinclude(char *str) { INCFILE *inf; FILE *fi; if ((fi = pfopen(str, "r")) != NULL) { if (F_verbose > 1 && F_verbose != 5 ) printf("%.*s Including file \"%s\"\n", Inclevel*4, "", str); ++Inclevel; if (F_listfile) fprintf(FI_listfile, "------- FILE %s LEVEL %d PASS %d\n", str, Inclevel, pass); inf = (INCFILE *)zmalloc(sizeof(INCFILE)); inf->next = pIncfile; inf->name = strcpy(ckmalloc(strlen(str)+1), str); inf->fi = fi; inf->lineno = 0; pIncfile = inf; return; } printf("Warning: Unable to open '%s'\n", str); return; }
void setvareq(shinstance *psh, char *s, int flags) { struct var *vp, **vpp; int nlen; if (aflag(psh)) flags |= VEXPORT; vp = find_var(psh, s, &vpp, &nlen); if (vp != NULL) { if (vp->flags & VREADONLY) error(psh, "%.*s: is read only", vp->name_len, s); if (flags & VNOSET) return; INTOFF; if (vp->func && (flags & VNOFUNC) == 0) (*vp->func)(psh, s + vp->name_len + 1); if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) ckfree(psh, vp->text); vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); vp->flags |= flags & ~VNOFUNC; vp->text = s; #ifdef PC_OS2_LIBPATHS if ((vp->flags & VOS2LIBPATH) && (vp->flags & VEXPORT)) vp->flags &= ~VEXPORT; #endif /* * We could roll this to a function, to handle it as * a regular variable function callback, but why bother? */ if (vp == &psh->vmpath || (vp == &psh->vmail && ! mpathset(psh))) chkmail(psh, 1); INTON; return; } /* not found */ if (flags & VNOSET) return; #ifdef PC_MIXED_PATH_VAR_NAME if ( nlen == 4 && (s[0] == 'p' || s[0] == 'P') && (s[1] == 'a' || s[1] == 'A') && (s[2] == 't' || s[2] == 'T') && (s[3] == 'h' || s[3] == 'H') ) { s[0] = 'P'; s[1] = 'A'; s[2] = 'T'; s[3] = 'H'; } #endif vp = ckmalloc(psh, sizeof (*vp)); vp->flags = flags & ~VNOFUNC; vp->text = s; vp->name_len = nlen; vp->next = *vpp; vp->func = NULL; *vpp = vp; }
STATIC int readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) { int c = firstc; char *out; int len; char line[EOFMARKLEN + 1]; struct nodelist *bqlist; int quotef; int dblquote; int varnest; /* levels of variables expansion */ int arinest; /* levels of arithmetic expansion */ int parenlevel; /* levels of parens in arithmetic */ int oldstyle; char const *prevsyntax; /* syntax before arithmetic */ int synentry; #if __GNUC__ /* Avoid longjmp clobbering */ (void) &out; (void) "ef; (void) &dblquote; (void) &varnest; (void) &arinest; (void) &parenlevel; (void) &oldstyle; (void) &prevsyntax; (void) &syntax; (void) &synentry; #endif startlinno = plinno; dblquote = 0; if (syntax == DQSYNTAX) dblquote = 1; quotef = 0; bqlist = NULL; varnest = 0; arinest = 0; parenlevel = 0; STARTSTACKSTR(out); loop: { /* for each line, until end of word */ CHECKEND(); /* set c to PEOF if at end of here document */ for (;;) { /* until end of line or end of word */ CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */ synentry = syntax[c]; switch(synentry) { case CNL: /* '\n' */ if (syntax == BASESYNTAX) goto endword; /* exit outer loop */ USTPUTC(c, out); plinno++; if (doprompt) setprompt(2); else setprompt(0); c = pgetc(); goto loop; /* continue outer loop */ case CWORD: USTPUTC(c, out); break; case CCTL: if (eofmark == NULL || dblquote) USTPUTC(CTLESC, out); USTPUTC(c, out); break; case CBACK: /* backslash */ c = pgetc(); if (c == PEOF) { USTPUTC('\\', out); pungetc(); } else if (c == '\n') { if (doprompt) setprompt(2); else setprompt(0); } else { if (dblquote && c != '\\' && c != '`' && c != '$' && (c != '"' || eofmark != NULL)) USTPUTC('\\', out); if (SQSYNTAX[c] == CCTL) USTPUTC(CTLESC, out); else if (eofmark == NULL) USTPUTC(CTLQUOTEMARK, out); USTPUTC(c, out); quotef++; } break; case CSQUOTE: if (eofmark == NULL) USTPUTC(CTLQUOTEMARK, out); syntax = SQSYNTAX; break; case CDQUOTE: if (eofmark == NULL) USTPUTC(CTLQUOTEMARK, out); syntax = DQSYNTAX; dblquote = 1; break; case CENDQUOTE: if (eofmark != NULL && arinest == 0 && varnest == 0) { USTPUTC(c, out); } else { if (arinest) { syntax = ARISYNTAX; dblquote = 0; } else if (eofmark == NULL) { syntax = BASESYNTAX; dblquote = 0; } quotef++; } break; case CVAR: /* '$' */ PARSESUB(); /* parse substitution */ break; case CENDVAR: /* '}' */ if (varnest > 0) { varnest--; USTPUTC(CTLENDVAR, out); } else { USTPUTC(c, out); } break; case CLP: /* '(' in arithmetic */ parenlevel++; USTPUTC(c, out); break; case CRP: /* ')' in arithmetic */ if (parenlevel > 0) { USTPUTC(c, out); --parenlevel; } else { if (pgetc() == ')') { if (--arinest == 0) { USTPUTC(CTLENDARI, out); syntax = prevsyntax; if (syntax == DQSYNTAX) dblquote = 1; else dblquote = 0; } else USTPUTC(')', out); } else { /* * unbalanced parens * (don't 2nd guess - no error) */ pungetc(); USTPUTC(')', out); } } break; case CBQUOTE: /* '`' */ PARSEBACKQOLD(); break; case CEOF: goto endword; /* exit outer loop */ default: if (varnest == 0) goto endword; /* exit outer loop */ USTPUTC(c, out); } c = pgetc_macro(); } } endword: if (syntax == ARISYNTAX) synerror("Missing '))'"); if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL) synerror("Unterminated quoted string"); if (varnest != 0) { startlinno = plinno; synerror("Missing '}'"); } USTPUTC('\0', out); len = out - stackblock(); out = stackblock(); if (eofmark == NULL) { if ((c == '>' || c == '<') && quotef == 0 && len <= 2 && (*out == '\0' || is_digit(*out))) { PARSEREDIR(); return lasttoken = TREDIR; } else { pungetc(); } } quoteflag = quotef; backquotelist = bqlist; grabstackblock(len); wordtext = out; return lasttoken = TWORD; /* end of readtoken routine */ /* * Check to see whether we are at the end of the here document. When this * is called, c is set to the first character of the next input line. If * we are at the end of the here document, this routine sets the c to PEOF. */ checkend: { if (eofmark) { if (striptabs) { while (c == '\t') c = pgetc(); } if (c == *eofmark) { if (pfgets(line, sizeof line) != NULL) { char *p, *q; p = line; for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); if (*p == '\n' && *q == '\0') { c = PEOF; plinno++; needprompt = doprompt; } else { pushstring(line, strlen(line), NULL); } } } } goto checkend_return; } /* * Parse a redirection operator. The variable "out" points to a string * specifying the fd to be redirected. The variable "c" contains the * first character of the redirection operator. */ parseredir: { char fd = *out; union node *np; np = (union node *)stalloc(sizeof (struct nfile)); if (c == '>') { np->nfile.fd = 1; c = pgetc(); if (c == '>') np->type = NAPPEND; else if (c == '&') np->type = NTOFD; else if (c == '|') np->type = NCLOBBER; else { np->type = NTO; pungetc(); } } else { /* c == '<' */ np->nfile.fd = 0; c = pgetc(); if (c == '<') { if (sizeof (struct nfile) != sizeof (struct nhere)) { np = (union node *)stalloc(sizeof (struct nhere)); np->nfile.fd = 0; } np->type = NHERE; heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); heredoc->here = np; if ((c = pgetc()) == '-') { heredoc->striptabs = 1; } else { heredoc->striptabs = 0; pungetc(); } } else if (c == '&') np->type = NFROMFD; else if (c == '>') np->type = NFROMTO; else { np->type = NFROM; pungetc(); } } if (fd != '\0') np->nfile.fd = digit_val(fd); redirnode = np; goto parseredir_return; } /* * Parse a substitution. At this point, we have read the dollar sign * and nothing else. */ parsesub: { int subtype; int typeloc; int flags; char *p; #ifndef GDB_HACK static const char types[] = "}-+?="; #endif int bracketed_name = 0; /* used to handle ${[0-9]*} variables */ c = pgetc(); if (c != '(' && c != '{' && !is_name(c) && !is_special(c)) { USTPUTC('$', out); pungetc(); } else if (c == '(') { /* $(command) or $((arith)) */ if (pgetc() == '(') { PARSEARITH(); } else { pungetc(); PARSEBACKQNEW(); } } else { USTPUTC(CTLVAR, out); typeloc = out - stackblock(); USTPUTC(VSNORMAL, out); subtype = VSNORMAL; if (c == '{') { bracketed_name = 1; c = pgetc(); if (c == '#') { if ((c = pgetc()) == '}') c = '#'; else subtype = VSLENGTH; } else subtype = 0; } if (is_name(c)) { do { STPUTC(c, out); c = pgetc(); } while (is_in_name(c)); } else if (is_digit(c)) { if (bracketed_name) { do { STPUTC(c, out); c = pgetc(); } while (is_digit(c)); } else { STPUTC(c, out); c = pgetc(); } } else { if (! is_special(c)) badsub: synerror("Bad substitution"); USTPUTC(c, out); c = pgetc(); } STPUTC('=', out); flags = 0; if (subtype == 0) { switch (c) { case ':': flags = VSNUL; c = pgetc(); /*FALLTHROUGH*/ default: p = strchr(types, c); if (p == NULL) goto badsub; subtype = p - types + VSNORMAL; break; case '%': case '#': { int cc = c; subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT; c = pgetc(); if (c == cc) subtype++; else pungetc(); break; } } } else { pungetc(); } if (subtype != VSLENGTH && (dblquote || arinest)) flags |= VSQUOTE; *(stackblock() + typeloc) = subtype | flags; if (subtype != VSNORMAL) varnest++; } goto parsesub_return; } /* * Called to parse command substitutions. Newstyle is set if the command * is enclosed inside $(...); nlpp is a pointer to the head of the linked * list of commands (passed by reference), and savelen is the number of * characters on the top of the stack which must be preserved. */ parsebackq: { struct nodelist **nlpp; int savepbq; union node *n; char *volatile str; struct jmploc jmploc; struct jmploc *volatile savehandler; int savelen; int saveprompt; #if __GNUC__ /* Avoid longjmp clobbering */ (void) &saveprompt; #endif savepbq = parsebackquote; if (setjmp(jmploc.loc)) { if (str) ckfree(str); parsebackquote = 0; handler = savehandler; longjmp(handler->loc, 1); } INTOFF; str = NULL; savelen = out - stackblock(); if (savelen > 0) { str = ckmalloc(savelen); memcpy(str, stackblock(), savelen); } savehandler = handler; handler = &jmploc; INTON; if (oldstyle) { /* We must read until the closing backquote, giving special treatment to some slashes, and then push the string and reread it as input, interpreting it normally. */ char *out; int c; int savelen; char *str; STARTSTACKSTR(out); for (;;) { if (needprompt) { setprompt(2); needprompt = 0; } switch (c = pgetc()) { case '`': goto done; case '\\': if ((c = pgetc()) == '\n') { plinno++; if (doprompt) setprompt(2); else setprompt(0); /* * If eating a newline, avoid putting * the newline into the new character * stream (via the STPUTC after the * switch). */ continue; } if (c != '\\' && c != '`' && c != '$' && (!dblquote || c != '"')) STPUTC('\\', out); break; case '\n': plinno++; needprompt = doprompt; break; case PEOF: startlinno = plinno; synerror("EOF in backquote substitution"); break; default: break; } STPUTC(c, out); } done: STPUTC('\0', out); savelen = out - stackblock(); if (savelen > 0) { str = ckmalloc(savelen); memcpy(str, stackblock(), savelen); setinputstring(str, 1); } } nlpp = &bqlist; while (*nlpp) nlpp = &(*nlpp)->next; *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); (*nlpp)->next = NULL; parsebackquote = oldstyle; if (oldstyle) { saveprompt = doprompt; doprompt = 0; } n = list(0); if (oldstyle) doprompt = saveprompt; else { if (readtoken() != TRP) synexpect(TRP); } (*nlpp)->n = n; if (oldstyle) { /* * Start reading from old file again, ignoring any pushed back * tokens left from the backquote parsing */ popfile(); tokpushback = 0; } while (stackblocksize() <= savelen) growstackblock(); STARTSTACKSTR(out); if (str) { memcpy(out, str, savelen); STADJUST(savelen, out); INTOFF; ckfree(str); str = NULL; INTON; } parsebackquote = savepbq; handler = savehandler; if (arinest || dblquote) USTPUTC(CTLBACKQ | CTLQUOTE, out); else USTPUTC(CTLBACKQ, out); if (oldstyle) goto parsebackq_oldreturn; else goto parsebackq_newreturn; } /* * Parse an arithmetic expansion (indicate start of one and set state) */ parsearith: { if (++arinest == 1) { prevsyntax = syntax; syntax = ARISYNTAX; USTPUTC(CTLARI, out); if (dblquote) USTPUTC('"',out); else USTPUTC(' ',out); } else { /* * we collapse embedded arithmetic expansion to * parenthesis, which should be equivalent */ USTPUTC('(', out); } goto parsearith_return; } } /* end of readtoken */
void redirect(union node *redir, int flags) { union node *n; struct redirtab *sv = NULL; int i; int fd; char memory[10]; /* file descriptors to write to memory */ for (i = 10 ; --i >= 0 ; ) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; if (flags & REDIR_PUSH) { /* We don't have to worry about REDIR_VFORK here, as * flags & REDIR_PUSH is never true if REDIR_VFORK is set. */ sv = ckmalloc(sizeof (struct redirtab)); sv->renamed = NULL; sv->next = redirlist; redirlist = sv; } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) { /* redirect from/to same file descriptor */ /* make sure it stays open */ if (fcntl(fd, F_SETFD, 0) < 0) error("fd %d: %s", fd, strerror(errno)); continue; } if ((flags & REDIR_PUSH) && !is_renamed(sv->renamed, fd)) { INTOFF; if (big_sh_fd < 10) find_big_fd(); if ((i = fcntl(fd, F_DUPFD, big_sh_fd)) == -1) { switch (errno) { case EBADF: i = CLOSED; break; case EMFILE: case EINVAL: find_big_fd(); i = fcntl(fd, F_DUPFD, big_sh_fd); if (i >= 0) break; /* FALLTHRU */ default: i = errno; INTON; /* XXX not needed here ? */ error("%d: %s", fd, strerror(i)); /* NOTREACHED */ } } if (i >= 0) (void)fcntl(i, F_SETFD, FD_CLOEXEC); fd_rename(sv, fd, i); INTON; } if (fd == 0) fd0_redirected++; openredirect(n, memory, flags); } if (memory[1]) out1 = &memout; if (memory[2]) out2 = &memout; }
void initvar(shinstance *psh) { const struct varinit *ip; struct var *vp; struct var **vpp; #ifdef PC_OS2_LIBPATHS char *psz = ckmalloc(psh, 2048); int rc; int i; for (i = 0; i < 4; i++) { psh->libpath_vars[i].flags = VSTRFIXED | VOS2LIBPATH; psh->libpath_vars[i].func = NULL; if (i > 0) { psz[0] = psz[1] = psz[2] = psz[3] = '\0'; rc = DosQueryExtLIBPATH(psz, i); } else { rc = DosQueryHeaderInfo(NULLHANDLE, 0, psz, 2048, QHINF_LIBPATH); psh->libpath_vars[i].flags |= VREADONLY; } if (!rc && *psz) { int cch1 = strlen(libpath_envs[i]); int cch2 = strlen(psz) + 1; psh->libpath_vars[i].text = ckmalloc(psh, cch1 + cch2); memcpy(psh->libpath_vars[i].text, libpath_envs[i], cch1); memcpy(psh->libpath_vars[i].text + cch1, psz, cch2); } else { psh->libpath_vars[i].flags |= VUNSET | VTEXTFIXED; psh->libpath_vars[i].text = (char*)libpath_envs[i]; } if (find_var(psh, psh->libpath_vars[i].text, &vpp, &psh->libpath_vars[i].name_len) != NULL) continue; psh->libpath_vars[i].next = *vpp; *vpp = &psh->libpath_vars[i]; } ckfree(psh, psz); #endif for (ip = varinit; ip->text; ip++) { vp = (struct var *)((char *)psh + ip->var_off); if (find_var(psh, ip->text, &vpp, &vp->name_len) != NULL) continue; vp->next = *vpp; *vpp = vp; vp->text = sh_strdup(psh, ip->text); vp->flags = ip->flags; vp->func = ip->func; } /* * PS1 depends on uid */ if (find_var(psh, "PS1", &vpp, &psh->vps1.name_len) == NULL) { psh->vps1.next = *vpp; *vpp = &psh->vps1; #ifdef KBUILD_VERSION_MAJOR psh->vps1.text = sh_strdup(psh, sh_geteuid(psh) ? "PS1=kash$ " : "PS1=kash# "); #else psh->vps1.text = sh_strdup(psh, sh_geteuid(psh) ? "PS1=$ " : "PS1=# "); #endif psh->vps1.flags = VSTRFIXED|VTEXTFIXED; } }
/* bTableSort true -> by address, false -> by name [phf] */ static void ShowSymbols( FILE *file, bool bTableSort ) { /* Display sorted (!) symbol table - if it runs out of memory, table will be displayed unsorted */ SYMBOL **symArray; SYMBOL *sym; int i; int nSymbols = 0; fprintf( file, "--- Symbol List"); /* Sort the symbol list either via name, or by value */ /* First count the number of symbols */ for (i = 0; i < SHASHSIZE; ++i) for (sym = SHash[i]; sym; sym = sym->next) nSymbols++; /* Malloc an array of pointers to data */ symArray = (SYMBOL **)ckmalloc( sizeof( SYMBOL * ) * nSymbols ); if ( !symArray ) { fprintf( file, " (unsorted - not enough memory to sort!)\n" ); /* Display complete symbol table */ for (i = 0; i < SHASHSIZE; ++i) for (sym = SHash[i]; sym; sym = sym->next) fprintf( file, "%-24s %s\n", sym->name, sftos( sym->value, sym->flags ) ); } else { /* Copy the element pointers into the symbol array */ int nPtr = 0; for (i = 0; i < SHASHSIZE; ++i) for (sym = SHash[i]; sym; sym = sym->next) symArray[ nPtr++ ] = sym; if ( bTableSort ) { fprintf( file, " (sorted by address)\n" ); qsort( symArray, nPtr, sizeof( SYMBOL * ), CompareAddress ); /* Sort via address */ } else { fprintf( file, " (sorted by symbol)\n" ); qsort( symArray, nPtr, sizeof( SYMBOL * ), CompareAlpha ); /* Sort via name */ } /* now display sorted list */ for ( i = 0; i < nPtr; i++ ) { fprintf( file, "%-24s %-12s", symArray[ i ]->name, sftos( symArray[ i ]->value, symArray[ i ]->flags ) ); if ( symArray[ i ]->flags & SYM_STRING ) fprintf( file, " \"%s\"", symArray[ i ]->string ); /* If a string, display actual string */ fprintf( file, "\n" ); } free( symArray ); } fputs( "--- End of Symbol List.\n", file ); }
void redirect(union node *redir, int flags) { union node *n; struct redirtab *sv; int i; int fd; int newfd; int *p; #if notyet char memory[10]; /* file descriptors to write to memory */ for (i = 10 ; --i >= 0 ; ) memory[i] = 0; memory[1] = flags & REDIR_BACKQ; #endif nullredirs++; if (!redir) { return; } sv = NULL; INTOFF; if (flags & REDIR_PUSH) { struct redirtab *q; q = ckmalloc(sizeof (struct redirtab)); q->next = redirlist; redirlist = q; q->nullredirs = nullredirs - 1; for (i = 0 ; i < 10 ; i++) q->renamed[i] = EMPTY; nullredirs = 0; sv = q; } n = redir; do { fd = n->nfile.fd; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) continue; /* redirect from/to same file descriptor */ newfd = openredirect(n); if (fd == newfd) continue; if (sv && *(p = &sv->renamed[fd]) == EMPTY) { int i = fcntl(fd, F_DUPFD, 10); if (i == -1) { i = errno; if (i != EBADF) { const char *m = strerror(i); close(newfd); sh_error("%d: %s", fd, m); /* NOTREACHED */ } } else { *p = i; close(fd); } } else { close(fd); } #ifdef notyet dupredirect(n, newfd, memory); #else dupredirect(n, newfd); #endif } while ((n = n->nfile.next)); INTON; #ifdef notyet if (memory[1]) out1 = &memout; if (memory[2]) out2 = &memout; #endif if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0) preverrout.fd = sv->renamed[2]; }
static void setalias(const char *name, const char *val) { struct alias *ap, **app; app = hashalias(name); for (ap = *app; ap; ap = ap->next) { if (equal(name, ap->name)) { INTOFF; ckfree(ap->val); /* See HACK below. */ #ifdef notyet ap->val = savestr(val); #else { size_t len = strlen(val); ap->val = ckmalloc(len + 2); memcpy(ap->val, val, len); ap->val[len] = ' '; ap->val[len+1] = '\0'; } #endif INTON; return; } } /* not found */ INTOFF; ap = ckmalloc(sizeof (struct alias)); ap->name = savestr(name); /* * XXX - HACK: in order that the parser will not finish reading the * alias value off the input before processing the next alias, we * dummy up an extra space at the end of the alias. This is a crock * and should be re-thought. The idea (if you feel inclined to help) * is to avoid alias recursions. The mechanism used is: when * expanding an alias, the value of the alias is pushed back on the * input as a string and a pointer to the alias is stored with the * string. The alias is marked as being in use. When the input * routine finishes reading the string, it marks the alias not * in use. The problem is synchronization with the parser. Since * it reads ahead, the alias is marked not in use before the * resulting token(s) is next checked for further alias sub. The * H A C K is that we add a little fluff after the alias value * so that the string will not be exhausted. This is a good * idea ------- ***NOT*** */ #ifdef notyet ap->val = savestr(val); #else /* hack */ { size_t len = strlen(val); ap->val = ckmalloc(len + 2); memcpy(ap->val, val, len); ap->val[len] = ' '; /* fluff */ ap->val[len+1] = '\0'; } #endif ap->flag = 0; ap->next = *app; *app = ap; aliases++; INTON; }