Beispiel #1
0
Wc_t* wc_init(int mode)
{
	register int	n;
	register int	w;
	Wc_t*		wp;

	if (!(wp = (Wc_t*)stakalloc(sizeof(Wc_t))))
		return 0;
	if (!mbwide())
		wp->mb = 0;
#if _hdr_wchar && _hdr_wctype && _lib_iswctype
	else if (!(mode & WC_NOUTF8) && (lcinfo(LC_CTYPE)->lc->flags & LC_utf8))
		wp->mb = 1;
#endif
	else
		wp->mb = -1;
	w = mode & WC_WORDS;
	for (n = (1<<CHAR_BIT); --n >= 0;)
		wp->type[n] = (w && isspace(n)) ? WC_SP : 0;
	wp->type['\n'] = WC_SP|WC_NL;
	if ((mode & (WC_MBYTE|WC_WORDS)) && wp->mb > 0)
	{
		for (n = 0; n < 64; n++)
		{
			wp->type[0x80+n] |= WC_MB;
			if (n<32)
				wp->type[0xc0+n] |= WC_MB+1;
			else if (n<48)
				wp->type[0xc0+n] |= WC_MB+2;
			else if (n<56)
				wp->type[0xc0+n] |= WC_MB+3;
			else if (n<60)
				wp->type[0xc0+n] |= WC_MB+4;
			else if (n<62)
				wp->type[0xc0+n] |= WC_MB+5;
		}
		wp->type[0xc0] = WC_MB|WC_ERR;
		wp->type[0xc1] = WC_MB|WC_ERR;
		wp->type[0xfe] = WC_MB|WC_ERR;
		wp->type[0xff] = WC_MB|WC_ERR;
	}
	wp->mode = mode;
	return wp;
}
Beispiel #2
0
static Cut_t*
cutinit(int mode, char* str, Delim_t* wdelim, Delim_t* ldelim, size_t reclen)
{
	register int*	lp;
	register int	c;
	register int	n = 0;
	register int	range = 0;
	register char*	cp = str;
	Cut_t*		cut;

	if (!(cut = (Cut_t*)stakalloc(sizeof(Cut_t) + strlen(cp) * sizeof(int))))
		error(ERROR_exit(1), "out of space");
	if (cut->mb = mbwide())
	{
		memset(cut->space, 0, sizeof(cut->space) / 2);
		memset(cut->space + sizeof(cut->space) / 2, SP_WIDE, sizeof(cut->space) / 2);
	}
	else
		memset(cut->space, 0, sizeof(cut->space));
	cut->wdelim = *wdelim;
	if (wdelim->len == 1)
		cut->space[wdelim->chr] = SP_WORD;
	cut->ldelim = *ldelim;
	cut->eob = (ldelim->len == 1) ? ldelim->chr : 0;
	cut->space[cut->eob] = SP_LINE;
	cut->cflag = (mode&C_CHARS) && cut->mb;
	cut->nosplit = (mode&(C_BYTES|C_NOSPLIT)) == (C_BYTES|C_NOSPLIT) && cut->mb;
	cut->sflag = (mode&C_SUPRESS) != 0;
	cut->nlflag = (mode&C_NONEWLINE) != 0;
	cut->reclen = reclen;
	lp = cut->list;
	for (;;)
		switch(c = *cp++)
		{
		case ' ':
		case '\t':
			while(*cp==' ' || *cp=='\t')
				cp++;
			/*FALLTHROUGH*/
		case 0:
		case ',':
			if(range)
			{
				--range;
				if((n = (n ? (n-range) : (HUGE-1))) < 0)
					error(ERROR_exit(1),"invalid range for c/f option");
				*lp++ = range;
				*lp++ = n;
			}
			else
			{
				*lp++ = --n;
				*lp++ = 1;
			}
			if(c==0)
			{
				register int *dp;
				*lp = HUGE;
				n = 1 + (lp-cut->list)/2;
				qsort(lp=cut->list,n,2*sizeof(*lp),mycomp);
				/* eliminate overlapping regions */
				for(n=0,range= -2,dp=lp; *lp!=HUGE; lp+=2)
				{
					if(lp[0] <= range)
					{
						if(lp[1]==HUGE)
						{
							dp[-1] = HUGE;
							break;
						}
						if((c = lp[0]+lp[1]-range)>0)
						{
							range += c;
							dp[-1] += c;
						}
					}
					else
					{
						range = *dp++ = lp[0];
						if(lp[1]==HUGE)
						{
							*dp++ = HUGE;
							break;
						}
						range += (*dp++ = lp[1]);
					}
				}
				*dp = HUGE;
				lp = cut->list;
				/* convert ranges into gaps */
				for(n=0; *lp!=HUGE; lp+=2)
				{
					c = *lp;
					*lp -= n;
					n = c+lp[1];
				}
				return cut;
			}
			n = range = 0;
			break;

		case '-':
			if(range)
				error(ERROR_exit(1),"bad list for c/f option");
			range = n?n:1;
			n = 0;
			break;

		default:
			if(!isdigit(c))
				error(ERROR_exit(1),"bad list for c/f option");
			n = 10*n + (c-'0');
			break;
		}
	/* NOTREACHED */
}
Beispiel #3
0
int
b_paste(int argc, char** argv, Shbltin_t* context)
{
	register int		n, sflag=0;
	register Sfio_t		*fp, **streams;
	register char 		*cp, *delim;
	char			*ep;
	Delim_t			*mp;
	int			dlen, dsiz;
	char			defdelim[2];

	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
	delim = 0;
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'd':
			delim = opt_info.arg;
			continue;
		case 's':
			sflag++;
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			break;
		case '?':
			error(ERROR_usage(2), "%s", opt_info.arg);
			break;
		}
		break;
	}
	argv += opt_info.index;
	if(error_info.errors)
		error(ERROR_usage(2),"%s", optusage(NiL));
	if(!delim || !*delim)
	{
		delim = defdelim;
		delim[0] = '\t';
		delim[1] = 0;
	}
	if (!(delim = strdup(delim)))
		error(ERROR_system(1), "out of space");
	dlen = dsiz = stresc(delim);
	mp = 0;
	if (mbwide())
	{
		cp = delim;
		ep = delim + dlen;
		dlen = 0;
		while (cp < ep)
		{
			mbchar(cp);
			dlen++;
		}
		if(dlen < dsiz)
		{
			if (!(mp = newof(0, Delim_t, dlen, 0)))
			{
				free(delim);
				error(ERROR_system(1), "out of space");
			}
			cp = delim;
			dlen = 0;
			while (cp < ep)
			{
				mp[dlen].chr = cp;
				mbchar(cp);
				mp[dlen].len = cp - mp[dlen].chr;
				dlen++;
			}
		}
	}
	if(cp = *argv)
	{
		n = argc - opt_info.index;
		argv++;
	}
	else
		n = 1;
	if(!sflag)
	{
		if (!(streams = (Sfio_t**)stakalloc(n*sizeof(Sfio_t*))))
			error(ERROR_exit(1), "out of space");
		n = 0;
	}
	do
	{
		if(!cp || streq(cp,"-"))
			fp = sfstdin;
		else if(!(fp = sfopen(NiL,cp,"r")))
			error(ERROR_system(0),"%s: cannot open",cp);
		if(fp && sflag)
		{
			if(spaste(fp,sfstdout,delim,dsiz,dlen,mp) < 0)
				error(ERROR_system(0),"write failed");
			if(fp!=sfstdin)
				sfclose(fp);
		}
		else if(!sflag)
			streams[n++] = fp;
	} while(cp= *argv++);
	if(!sflag)
	{
		if(error_info.errors==0 && paste(n,streams,sfstdout,delim,dsiz,dlen,mp) < 0)
			error(ERROR_system(0),"write failed");
		while(--n>=0)
			if((fp=streams[n]) && fp!=sfstdin)
				sfclose(fp);
	}
	if (mp)
		free(mp);
	free(delim);
	return(error_info.errors);
}
Beispiel #4
0
int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
{
	struct comnod	*comptr;
	struct argnod	*ap;
	register char	*out;
	char 		*av[2], *begin , *dir=0;
	int		addstar=0, rval=0, var=0, strip=1;
	int 		nomarkdirs = !sh_isoption(SH_MARKDIRS);
	sh_onstate(SH_FCOMPLETE);
	if(ep->e_nlist)
	{
		if(mode=='=' && count>0)
		{
			if(count> ep->e_nlist)
				return(-1);
			mode = '?';
			av[0] = ep->e_clist[count-1];
			av[1] = 0;
		}
		else
		{
			stakset(ep->e_stkptr,ep->e_stkoff);
			ep->e_nlist = 0;
		}
	}
	comptr = (struct comnod*)stakalloc(sizeof(struct comnod));
	ap = (struct argnod*)stakseek(ARGVAL);
#if SHOPT_MULTIBYTE
	{
		register int c = *cur;
		register genchar *cp;
		/* adjust cur */
		cp = (genchar *)outbuff + *cur;
		c = *cp;
		*cp = 0;
		*cur = ed_external((genchar*)outbuff,(char*)stakptr(0));
		*cp = c;
		*eol = ed_external((genchar*)outbuff,outbuff);
	}
#endif /* SHOPT_MULTIBYTE */
	out = outbuff + *cur + (sh_isoption(SH_VI)!=0);
	if(out[-1]=='"' || out[-1]=='\'')
	{
		rval = -(sh_isoption(SH_VI)!=0);
		goto done;
	}
	comptr->comtyp = COMSCAN;
	comptr->comarg = ap;
	ap->argflag = (ARG_MAC|ARG_EXP);
	ap->argnxt.ap = 0;
	ap->argchn.cp = 0;
	{
		register int c;
		char *last = out;
		c =  *(unsigned char*)out;
		var = mode;
		begin = out = find_begin(outbuff,last,0,&var);
		/* addstar set to zero if * should not be added */
		if(var=='$')
		{
			stakputs("${!");
			stakwrite(out,last-out);
			stakputs("@}");
			out = last;
		}
		else
		{
			addstar = '*';
			while(out < last)
			{
				c = *(unsigned char*)out;
				if(isexp(c))
					addstar = 0;
				if (c == '/')
				{
					if(addstar == 0)
						strip = 0;
					dir = out+1;
				}
				stakputc(c);
				out++;
			}
		}
		if(mode=='?')
			mode = '*';
		if(var!='$' && mode=='\\' && out[-1]!='*')
			addstar = '*';
		if(*begin=='~' && !strchr(begin,'/'))
			addstar = 0;
		stakputc(addstar);
		ap = (struct argnod*)stakfreeze(1);
	}
	if(mode!='*')
		sh_onoption(SH_MARKDIRS);
	{
		register char	**com;
		char		*cp=begin, *left=0, *saveout=".";
		int	 	nocase=0,narg,cmd_completion=0;
		register 	int size='x';
		while(cp>outbuff && ((size=cp[-1])==' ' || size=='\t'))
			cp--;
		if(!var && !strchr(ap->argval,'/') && (((cp==outbuff&&ep->sh->nextprompt==1) || (strchr(";&|(",size)) && (cp==outbuff+1||size=='('||cp[-2]!='>') && *begin!='~' )))
		{
			cmd_completion=1;
			sh_onstate(SH_COMPLETE);
		}
		if(ep->e_nlist)
		{
			narg = 1;
			com = av;
			if(dir)
				begin += (dir-begin);
		}
		else
		{
			com = sh_argbuild(ep->sh,&narg,comptr,0);
			/* special handling for leading quotes */
			if(begin>outbuff && (begin[-1]=='"' || begin[-1]=='\''))
			begin--;
		}
		sh_offstate(SH_COMPLETE);
                /* allow a search to be aborted */
		if(ep->sh->trapnote&SH_SIGSET)
		{
			rval = -1;
			goto done;
		}
		/*  match? */
		if (*com==0 || (narg <= 1 && (strcmp(ap->argval,*com)==0) || (addstar && com[0][strlen(*com)-1]=='*')))
		{
			rval = -1;
			goto done;
		}
		if(mode=='\\' && out[-1]=='/'  && narg>1)
			mode = '=';
		if(mode=='=')
		{
			if (strip && !cmd_completion)
			{
				register char **ptrcom;
				for(ptrcom=com;*ptrcom;ptrcom++)
					/* trim directory prefix */
					*ptrcom = path_basename(*ptrcom);
			}
			sfputc(sfstderr,'\n');
			sh_menu(sfstderr,narg,com);
			sfsync(sfstderr);
			ep->e_nlist = narg;
			ep->e_clist = com;
			goto done;
		}
		/* see if there is enough room */
		size = *eol - (out-begin);
		if(mode=='\\')
		{
			int c;
			if(dir)
			{
				c = *dir;
				*dir = 0;
				saveout = begin;
			}
			if(saveout=astconf("PATH_ATTRIBUTES",saveout,(char*)0))
				nocase = (strchr(saveout,'c')!=0);
			if(dir)
				*dir = c;
			/* just expand until name is unique */
			size += strlen(*com);
		}
		else
		{
			size += narg;
			{
				char **savcom = com;
				while (*com)
					size += strlen(cp=fmtx(*com++));
				com = savcom;
			}
		}
		/* see if room for expansion */
		if(outbuff+size >= &outbuff[MAXLINE])
		{
			com[0] = ap->argval;
			com[1] = 0;
		}
		/* save remainder of the buffer */
		if(*out)
			left=stakcopy(out);
		if(cmd_completion && mode=='\\')
			out = strcopy(begin,path_basename(cp= *com++));
		else if(mode=='*')
		{
			if(ep->e_nlist && dir && var)
			{
				if(*cp==var)
					cp++;
				else
					*begin++ = var;
				out = strcopy(begin,cp);
				var = 0;
			}
			else
				out = strcopy(begin,fmtx(*com));
			com++;
		}
		else
			out = strcopy(begin,*com++);
		if(mode=='\\')
		{
			saveout= ++out;
			while (*com && *begin)
			{
				if(cmd_completion)
					out = overlaid(begin,path_basename(*com++),nocase);
				else
					out = overlaid(begin,*com++,nocase);
			}
			mode = (out==saveout);
			if(out[-1]==0)
				out--;
			if(mode && out[-1]!='/')
			{
				if(cmd_completion)
				{
					Namval_t *np;
					/* add as tracked alias */
					Pathcomp_t *pp;
					if(*cp=='/' && (pp=path_dirfind(ep->sh->pathlist,cp,'/')) && (np=nv_search(begin,ep->sh->track_tree,NV_ADD)))
						path_alias(np,pp);
					out = strcopy(begin,cp);
				}
				/* add quotes if necessary */
				if((cp=fmtx(begin))!=begin)
					out = strcopy(begin,cp);
				if(var=='$' && begin[-1]=='{')
					*out = '}';
				else
					*out = ' ';
				*++out = 0;
			}
			else if((cp=fmtx(begin))!=begin)
			{
				out = strcopy(begin,cp);
				if(out[-1] =='"' || out[-1]=='\'')
					  *--out = 0;
			}
			if(*begin==0)
				ed_ringbell();
		}
		else
		{
			while (*com)
			{
				*out++  = ' ';
				out = strcopy(out,fmtx(*com++));
			}
		}
		if(ep->e_nlist)
		{
			cp = com[-1];
			if(cp[strlen(cp)-1]!='/')
			{
				if(var=='$' && begin[-1]=='{')
					*out = '}';
				else
					*out = ' ';
				out++;
			}
			else if(out[-1] =='"' || out[-1]=='\'')
				out--;
			*out = 0;
		}
		*cur = (out-outbuff);
		/* restore rest of buffer */
		if(left)
			out = strcopy(out,left);
		*eol = (out-outbuff);
	}
 done:
	sh_offstate(SH_FCOMPLETE);
	if(!ep->e_nlist)
		stakset(ep->e_stkptr,ep->e_stkoff);
	if(nomarkdirs)
		sh_offoption(SH_MARKDIRS);
#if SHOPT_MULTIBYTE
	{
		register int c,n=0;
		/* first re-adjust cur */
		c = outbuff[*cur];
		outbuff[*cur] = 0;
		for(out=outbuff; *out;n++)
			mbchar(out);
		outbuff[*cur] = c;
		*cur = n;
		outbuff[*eol+1] = 0;
		*eol = ed_internal(outbuff,(genchar*)outbuff);
	}
#endif /* SHOPT_MULTIBYTE */
	return(rval);
}
Beispiel #5
0
int
glob(const char* pattern, int flags, int (*errfn)(const char*, int), register glob_t* gp)
{
	register globlist_t*	ap;
	register char*		pat;
	globlist_t*		top;
	Stak_t*			oldstak;
	char**			argv;
	char**			av;
	size_t			skip;
	unsigned long		f;
	int			n;
	int			x;

	const char*		nocheck = pattern;
	int			optlen = 0;
	int			suflen = 0;
	int			extra = 1;
	unsigned char		intr = 0;

	gp->gl_rescan = 0;
	gp->gl_error = 0;
	gp->gl_errfn = errfn;
	if (flags & GLOB_APPEND)
	{
		if ((gp->gl_flags |= GLOB_APPEND) ^ (flags|GLOB_MAGIC))
			return GLOB_APPERR;
		if (((gp->gl_flags & GLOB_STACK) == 0) == (gp->gl_stak == 0))
			return GLOB_APPERR;
		if (gp->gl_starstar > 1)
			gp->gl_flags |= GLOB_STARSTAR;
		else
			gp->gl_starstar = 0;
	}
	else
	{
		gp->gl_flags = (flags&0xffff)|GLOB_MAGIC;
		gp->re_flags = REG_SHELL|REG_NOSUB|REG_LEFT|REG_RIGHT|((flags&GLOB_AUGMENTED)?REG_AUGMENTED:0);
		gp->gl_pathc = 0;
		gp->gl_ignore = 0;
		gp->gl_ignorei = 0;
		gp->gl_starstar = 0;
		if (!(flags & GLOB_DISC))
		{
			gp->gl_fignore = 0;
			gp->gl_suffix = 0;
			gp->gl_intr = 0;
			gp->gl_delim = 0;
			gp->gl_handle = 0;
			gp->gl_diropen = 0;
			gp->gl_dirnext = 0;
			gp->gl_dirclose = 0;
			gp->gl_type = 0;
			gp->gl_attr = 0;
			gp->gl_nextdir = 0;
			gp->gl_stat = 0;
			gp->gl_lstat = 0;
			gp->gl_extra = 0;
		}
		if (!(flags & GLOB_ALTDIRFUNC))
		{
			gp->gl_opendir = (GL_opendir_f)opendir;
			gp->gl_readdir = (GL_readdir_f)readdir;
			gp->gl_closedir = (GL_closedir_f)closedir;
			if (!gp->gl_stat)
				gp->gl_stat = (GL_stat_f)pathstat;
		}
		if (!gp->gl_lstat)
			gp->gl_lstat = (GL_stat_f)lstat;
		if (!gp->gl_intr)
			gp->gl_intr = &intr;
		if (!gp->gl_delim)
			gp->gl_delim = '/';
		if (!gp->gl_diropen)
			gp->gl_diropen = gl_diropen;
		if (!gp->gl_dirnext)
			gp->gl_dirnext = gl_dirnext;
		if (!gp->gl_dirclose)
			gp->gl_dirclose = gl_dirclose;
		if (!gp->gl_type)
			gp->gl_type = gl_type;
		if (!gp->gl_attr)
			gp->gl_attr = gl_attr;
		if (flags & GLOB_ICASE)
			gp->re_flags |= REG_ICASE;
		if (!gp->gl_fignore)
			gp->re_flags |= REG_SHELL_DOT;
		else if (*gp->gl_fignore)
		{
			if (regcomp(&gp->re_ignore, gp->gl_fignore, gp->re_flags))
				return GLOB_APPERR;
			gp->gl_ignore = &gp->re_ignore;
		}
		if (gp->gl_flags & GLOB_STACK)
			gp->gl_stak = 0;
		else if (!(gp->gl_stak = stakcreate(0)))
			return GLOB_NOSPACE;
		if ((gp->gl_flags & GLOB_COMPLETE) && !gp->gl_nextdir)
			gp->gl_nextdir = gl_nextdir;
	}
	skip = gp->gl_pathc;
	if (gp->gl_stak)
		oldstak = stakinstall(gp->gl_stak, 0);
	if (flags & GLOB_DOOFFS)
		extra += gp->gl_offs;
	if (gp->gl_suffix)
		suflen =  strlen(gp->gl_suffix);
	if (*(pat = (char*)pattern) == '~' && *(pat + 1) == '(')
	{
		f = gp->gl_flags;
		n = 1;
		x = 1;
		pat += 2;
		for (;;)
		{
			switch (*pat++)
			{
			case 0:
			case ':':
				break;
			case '-':
				n = 0;
				continue;
			case '+':
				n = 1;
				continue;
			case 'i':
				if (n)
					f |= GLOB_ICASE;
				else
					f &= ~GLOB_ICASE;
				continue;
			case 'M':
				if (n)
					f |= GLOB_BRACE;
				else
					f &= ~GLOB_BRACE;
				continue;
			case 'N':
				if (n)
					f &= ~GLOB_NOCHECK;
				else
					f |= GLOB_NOCHECK;
				continue;
			case 'O':
				if (n)
					f |= GLOB_STARSTAR;
				else
					f &= ~GLOB_STARSTAR;
				continue;
			case ')':
				flags = (gp->gl_flags = f) & 0xffff;
				if (f & GLOB_ICASE)
					gp->re_flags |= REG_ICASE;
				else
					gp->re_flags &= ~REG_ICASE;
				if (x)
					optlen = pat - (char*)pattern;
				break;
			default:
				x = 0;
				continue;
			}
			break;
		}
	}
	top = ap = (globlist_t*)stakalloc((optlen ? 2 : 1) * strlen(pattern) + sizeof(globlist_t) + suflen + gp->gl_extra);
	ap->gl_next = 0;
	ap->gl_flags = 0;
	ap->gl_begin = ap->gl_path + gp->gl_extra;
	pat = strcopy(ap->gl_begin, pattern + optlen);
	if (suflen)
		pat = strcopy(pat, gp->gl_suffix);
	gp->gl_pat = optlen ? strncpy(gp->gl_opt = pat + 1, pattern, optlen) : (char*)0;
	suflen = 0;
	if (!(flags & GLOB_LIST))
		gp->gl_match = 0;
	do
	{
		gp->gl_rescan = ap->gl_next;
		glob_dir(gp, ap);
	} while (!gp->gl_error && (ap = gp->gl_rescan));
	if (gp->gl_pathc == skip)
	{
		if (flags & GLOB_NOCHECK)
		{
			gp->gl_pathc++;
			top->gl_next = gp->gl_match;
			gp->gl_match = top;
			strcopy(top->gl_path + gp->gl_extra, nocheck);
		}
		else
			gp->gl_error = GLOB_NOMATCH;
	}
	if (flags & GLOB_LIST)
		gp->gl_list = gp->gl_match;
	else
	{
		argv = (char**)stakalloc((gp->gl_pathc + extra) * sizeof(char*));
		if (gp->gl_flags & GLOB_APPEND)
		{
			skip += --extra;
			memcpy(argv, gp->gl_pathv, skip * sizeof(char*));
			av = argv + skip;
		}
		else
		{
			av = argv;
			while (--extra > 0)
				*av++ = 0;
		}
		gp->gl_pathv = argv;
		argv = av;
		ap = gp->gl_match;
		while (ap)
		{
			*argv++ = ap->gl_path + gp->gl_extra;
			ap = ap->gl_next;
		}
		*argv = 0;
		if (!(flags & GLOB_NOSORT) && (argv - av) > 1)
		{
			strsort(av, argv - av, strcoll);
			if (gp->gl_starstar > 1)
				av[gp->gl_pathc = struniq(av, argv - av)] = 0;
			gp->gl_starstar = 0;
		}
	}
	if (gp->gl_starstar > 1)
		gp->gl_flags &= ~GLOB_STARSTAR;
	if (gp->gl_stak)
		stakinstall(oldstak, 0);
	return gp->gl_error;
}
Beispiel #6
0
int sh_access(register const char *name, register int mode)
{
	Shell_t	*shp = sh_getinterp();
	struct stat statb;
	if(*name==0)
		return(-1);
	if(sh_isdevfd(name))
		return(sh_ioaccess((int)strtol(name+8, (char**)0, 10),mode));
	/* can't use access function for execute permission with root */
	if(mode==X_OK && shp->gd->euserid==0)
		goto skip;
	if(shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid)
		return(access(name,mode));
#ifdef _lib_setreuid
	/* swap the real uid to effective, check access then restore */
	/* first swap real and effective gid, if different */
	if(shp->gd->groupid==shp->gd->euserid || setregid(shp->gd->egroupid,shp->gd->groupid)==0) 
	{
		/* next swap real and effective uid, if needed */
		if(shp->gd->userid==shp->gd->euserid || setreuid(shp->gd->euserid,shp->gd->userid)==0)
		{
			mode = access(name,mode);
			/* restore ids */
			if(shp->gd->userid!=shp->gd->euserid)
				setreuid(shp->gd->userid,shp->gd->euserid);
			if(shp->gd->groupid!=shp->gd->egroupid)
				setregid(shp->gd->groupid,shp->gd->egroupid);
			return(mode);
		}
		else if(shp->gd->groupid!=shp->gd->egroupid)
			setregid(shp->gd->groupid,shp->gd->egroupid);
	}
#endif /* _lib_setreuid */
skip:
	if(test_stat(name, &statb) == 0)
	{
		if(mode == F_OK)
			return(mode);
		else if(shp->gd->euserid == 0)
		{
			if(!S_ISREG(statb.st_mode) || mode!=X_OK)
				return(0);
		    	/* root needs execute permission for someone */
			mode = (S_IXUSR|S_IXGRP|S_IXOTH);
		}
		else if(shp->gd->euserid == statb.st_uid)
			mode <<= 6;
		else if(shp->gd->egroupid == statb.st_gid)
			mode <<= 3;
#ifdef _lib_getgroups
		/* on some systems you can be in several groups */
		else
		{
			static int maxgroups;
			gid_t *groups; 
			register int n;
			if(maxgroups==0)
			{
				/* first time */
				if((maxgroups=getgroups(0,(gid_t*)0)) <= 0)
				{
					/* pre-POSIX system */
					maxgroups=NGROUPS_MAX;
				}
			}
			groups = (gid_t*)stakalloc((maxgroups+1)*sizeof(gid_t));
			n = getgroups(maxgroups,groups);
			while(--n >= 0)
			{
				if(groups[n] == statb.st_gid)
				{
					mode <<= 3;
					break;
				}
			}
		}
#   endif /* _lib_getgroups */
		if(statb.st_mode & mode)
			return(0);
	}
	return(-1);
}
Beispiel #7
0
int
b_tee(int argc, register char** argv, void* context)
{
    register Tee_t*		tp = 0;
    register int		oflag = O_WRONLY|O_TRUNC|O_CREAT|O_BINARY;
    register int*		hp;
    register char*		cp;
    int			line;

    if (argc <= 0)
    {
        if (context && (tp = (Tee_t*)sh_context(context)->data))
        {
            sh_context(context)->data = 0;
            tee_cleanup(tp);
        }
        return 0;
    }
    cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_CALLBACK);
    line = -1;
    for (;;)
    {
        switch (optget(argv, usage))
        {
        case 'a':
            oflag &= ~O_TRUNC;
            oflag |= O_APPEND;
            continue;
        case 'i':
            signal(SIGINT, SIG_IGN);
            continue;
        case 'l':
            line = sfset(sfstdout, 0, 0) & SF_LINE;
            if ((line == 0) == (opt_info.num == 0))
                line = -1;
            else
                sfset(sfstdout, SF_LINE, !!opt_info.num);
            continue;
        case ':':
            error(2, "%s", opt_info.arg);
            break;
        case '?':
            error(ERROR_usage(2), "%s", opt_info.arg);
            break;
        }
        break;
    }
    if (error_info.errors)
        error(ERROR_usage(2), "%s", optusage(NiL));
    argv += opt_info.index;
    argc -= opt_info.index;
#if _ANCIENT_BSD_COMPATIBILITY
    if (*argv && streq(*argv, "-"))
    {
        signal(SIGINT, SIG_IGN);
        argv++;
        argc--;
    }
#endif
    if (argc > 0)
    {
        if (tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int)))
        {
            memset(&tp->disc, 0, sizeof(tp->disc));
            tp->disc.writef = tee_write;
            if (context)
                sh_context(context)->data = (void*)tp;
            tp->line = line;
            hp = tp->fd;
            while (cp = *argv++)
            {
                if ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
                    error(ERROR_system(0), "%s: cannot create", cp);
                else
                    hp++;
            }
            if (hp == tp->fd)
                tp = 0;
            else
            {
                *hp = -1;
                sfdisc(sfstdout, &tp->disc);
            }
        }
        else
            error(ERROR_exit(0), "out of space");
    }
    if ((sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin)) && errno != EPIPE)
        error(ERROR_system(0), "read error");
    if (sfsync(sfstdout))
        error(ERROR_system(0), "write error");
    tee_cleanup(tp);
    return error_info.errors;
}