Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- # shpipe -- self expanding paste archive
- #
- # CREATED 2016/03/03-00:01:50 UTC
- #
- # INFO shell with pipes
- #
- # arguments:
- # "-h" -- display help
- # "-help" -- display help (same as -h)
- # "-O<odir>" -- output directory
- # "-tail" -- remove subdirectory from individual files
- # "-x" -- extract files
- #
- # "-tab" -- tab control
- # 0 -- no change
- # 1 -- create tabs from spaces
- # 2 -- expand tabs to spaces at beginning of line
- # 3 -- expand tabs to spaces everywhere
- #
- # installation/extraction instructions:
- # (1) save this file to /where_ever_you_want
- # (2) perl /where_ever_you_want
- # (3) if perl not installed, try "yum install perl" [or equiv for your sys]
- # and repeat (2)
- #
- # how to extract manually:
- # after the data __DATA__ line there are optional default option lines
- #
- # each file is preceeded by:
- # % <file>
- # and the lines after that do _not_ start with "%" are the data for that file
- #
- # for example:
- # % file1
- # file1's line 1 ...
- # file1's line 2 ...
- # ...
- # file1's line n...
- # % file2
- # file2's line 1 ...
- # file2's line 2 ...
- # ...
- # file2's line n...
- master(@ARGV);
- exit(0);
- # master -- master control
- sub master
- {
- my(@argv) = @_;
- my($esc,$bf);
- my($otail,$ofile,$xfsrc,$xfdata,$xfdst);
- my($lno,$bytot,$bycnt);
- $pgmfile = $0;
- $pgmtail = filetail($pgmfile);
- select(STDOUT);
- $| = 1;
- select(STDERR);
- $| = 1;
- $esc = "%";
- open($xfsrc,"<$pgmfile");
- $xfdata = "joinup::DATA";
- $xfdata = \*$xfdata;
- $datapos = tell($xfdata);
- while ($bf = <$xfdata>) {
- $bycnt = length($bf);
- # process separater line
- if ($bf =~ s/^$esc\s+//) {
- if (defined($otail)) {
- printf("%d lines %d chars\n",$lno,$bytot)
- unless (defined($opf_lns));
- }
- else {
- optget(\@argv);
- if (defined($opt_h)) {
- usage($xfsrc);
- $opt_x = 0;
- }
- $opt_tail = 1
- if ($opt_O eq "-");
- }
- $otail = optfile($bf);
- undef($lno);
- undef($bytot);
- {
- $ofile = filetail($ofile)
- if ($opt_tail);
- $ofile = $otail;
- last if ($opt_O eq "-");
- last if ($opt_O eq "");
- $ofile = "$opt_O/$otail";
- }
- if (defined($opf_lns)) {
- printf("%s %s --> %s\n",
- $opt_x ? "LNS" : "LN?",$ofile,$opf_lns);
- }
- else {
- printf("%s %s -- ",
- $opt_x ? "EXTRACT" : "LIST",$ofile);
- }
- next unless ($opt_x);
- # always do this to ensure things work if overwrite and type
- # [symlink vs file] has changed
- unlink($ofile);
- close($xfdst);
- if (defined($opf_lns)) {
- next if (symlink($opf_lns,$ofile));
- sysfault("$pgmtail: unable to symlink '%s' to '%s' -- $!\n",
- $ofile,$opf_lns);
- }
- # open the file
- open($xfdst,">$ofile") ||
- sysfault("$pgmtail: unable to open '%s' -- $!\n",$ofile);
- # change permission
- if (defined($opf_chmod)) {
- $opf_chmod =~ s/^0+//;
- $opf_chmod = oct($opf_chmod);
- chmod($opf_chmod,$ofile);
- }
- next;
- }
- # handle data line
- if (defined($otail)) {
- ++$lno;
- $bytot += $bycnt;
- next unless ($opt_x);
- $bf = tabfix($bf)
- if ($opt_tab);
- print($xfdst $bf);
- next;
- }
- # handle default options
- if ($bf =~ /^-/) {
- chomp($bf);
- optget($bf);
- next;
- }
- # FIXME/CAE -- this is now junk/bad data
- printf("$pgmtail: INFO %s",$bf);
- }
- printf("%d lines %d chars\n",$lno,$bytot)
- if (defined($otail));
- close($xfdst);
- {
- last if ($opt_x);
- last if ($opt_h);
- printf("$pgmtail: rerun with -h to get help\n");
- printf("$pgmtail: rerun with -x to actually extract files\n");
- }
- close($xfsrc);
- }
- # optget -- decode command line options
- sub optget
- {
- my($argv) = @_;
- $argv = [$argv]
- unless (ref($argv));
- while (1) {
- vbqdash($argv);
- vbqstrdcd($_,"-h",1,\$opt_h);
- vbqstrdcd($_,"-O","-",\$opt_O);
- vbqnumdcd($_,"-tab",1,\$opt_tab);
- vbqnumdcd($_,"-tail",1,\$opt_tail);
- vbqnumdcd($_,"-x",1,\$opt_x);
- usage();
- }
- }
- # optfile -- decode per-file options
- sub optfile
- {
- my($bf) = @_;
- my($otail);
- chomp($bf);
- @cmdargv = split(" ",$bf);
- $otail = shift(@cmdargv);
- undef($opf_lns);
- undef($opf_chmod);
- while (1) {
- vbqdash(\@cmdargv);
- vbqstrdcd($_,"-lns",undef,\$opf_lns);
- vbqstrdcd($_,"-chmod","0755",\$opf_chmod);
- usage();
- }
- $otail;
- }
- # tabfix -- fix up tabs
- sub tabfix
- {
- my($rhs) = @_;
- my($pre);
- if ($bf =~ s/^(\s+)//) {
- $pre = $1;
- $pre =~ s/ /\t/g;
- $bf = $pre . $bf;
- }
- $bf;
- }
- # sysfault -- output error
- sub sysfault
- {
- printf(@_);
- exit(1);
- }
- # usage -- show usage
- sub usage
- {
- my($xfsrc) = @_;
- seek($xfsrc,0,0);
- while ($bf = <$xfsrc>) {
- chomp($bf);
- next if ($bf =~ /^#!/);
- last unless ($bf =~ s/^# ?//);
- print($bf,"\n");
- }
- }
- sub vbqdash
- {
- my($ptr) = @_;
- my($opt);
- $opt = $ptr->[0];
- last unless ($opt =~ /^-/);
- shift(@$ptr);
- last if ($opt eq "--");
- $_ = $opt
- unless (defined(wantarray));
- $opt;
- }
- sub vbqnumdcd
- {
- my($bf,$key,$dft,$var) = @_;
- if ($bf =~ /^$key(.*)$/) {
- my($val) = $1;
- $val =~ s/^=//s;
- $val = $dft
- if ($val eq "");
- $val += 0;
- vbqchk($var,"vbqnumdcd");
- $$var = $val;
- next;
- }
- }
- sub vbqstrdcd
- {
- my($bf,$key,$dft,$var) = @_;
- if ($bf =~ /^$key(.*)$/s) {
- my($val) = $1;
- $val =~ s/^=//;
- $val = $dft
- if ($val eq "");
- vbqchk($var,"vbqstrdcd");
- $$var = $val
- if (defined($val));
- next;
- }
- }
- sub vbqchk
- # ptr -- pointer to check
- # reason -- reason for call
- {
- my($ptr,$reason) = @_;
- my($typ);
- my($ok);
- if (defined(&blesscore)) {
- $typ = blesscore($ptr);
- }
- else {
- $typ = $ptr;
- $typ =~ s/[(].+$//;
- }
- if ($reason =~ /^vbqv/) {
- $ok = ($typ eq "ARRAY");
- }
- else {
- $ok = ($typ eq "SCALAR");
- }
- unless ($ok) {
- $ptr = prtstr($ptr)
- if (defined(&prtstr));
- vbqfault("!vbqchk: invalid pointer -- ptr=%s reason='%s'\n",
- $ptr,$reason);
- }
- }
- sub vbqusage
- {
- my($opt,$reason) = @_;
- if ($reason =~ s/^!//) {
- vbqzprtx("$reason: unknown option -- '%s'\n",$opt);
- }
- else {
- vbqfault("!$reason: unknown option -- '%s'\n",$opt);
- }
- }
- sub vbqzprtx
- {
- goto &_zprtx
- if (defined(&_zprtx));
- printf(STDERR @_);
- }
- sub vbqfault
- {
- goto &sysfault
- if (defined(&sysfault));
- vbqzprtx(@_);
- exit(1);
- }
- sub filetail
- {
- my($file) = @_;
- $file =~ s,.*/,,g;
- $file;
- }
- package joinup;
- __DATA__
- -O-
- % dlk.c
- // shpipe/dlk -- "smart" list "class" for C
- #include <shpipe.h>
- // dlhfree -- free list
- dlh_p
- dlhfree(dlh_p dlh)
- {
- _dlhfree(dlh);
- sysfree(dlh);
- dlh = NULL;
- return dlh;
- }
- // _dlhfree -- clean list
- dlh_p
- _dlhfree(dlh_p dlh)
- {
- dlv_p dlv;
- dlk_p dlk;
- dlk_p next;
- dlv = dlh->dlh_dlv;
- for (dlk = dlh->dlh_head; dlk != NULL; dlk = next) {
- next = dlk->dlk_next;
- dlv->dlv_free(dlk);
- }
- dlh = NULL;
- return dlh;
- }
- // dlkpush -- append string to end of list
- dlk_p
- dlkpush(dlh_p dlh,dlk_p dlk)
- {
- dlk_p tail;
- tail = dlh->dlh_tail;
- dlk->dlk_next = NULL;
- dlk->dlk_prev = tail;
- if (tail != NULL)
- tail->dlk_next = dlk;
- dlh->dlh_tail = dlk;
- if (dlh->dlh_head == NULL)
- dlh->dlh_head = dlk;
- dlhinc(dlh,1);
- return dlk;
- }
- // dlhcut -- cut out entry and split list
- void
- dlhcut(dlh_p dlhlhs,dlh_p dlhrhs,dlk_p dlk)
- {
- dlk_p prev;
- dlk_p next;
- dbgprt(1,"dlhcut: ENTER\n");
- dbgexec(1,dlhrhs->dlh_dlv->dlv_show(dlk,"dlhcut"));
- dbgexec(1,dlhshow(dlhrhs,"dlhrhs/BEF"));
- prev = dlk->dlk_prev;
- next = dlk->dlk_next;
- // set left side list
- dlhlhs->dlh_tail = prev;
- if (dlk == dlhrhs->dlh_head)
- dlhlhs->dlh_head = NULL;
- else
- dlhlhs->dlh_head = dlhrhs->dlh_head;
- // set right side list
- dlhrhs->dlh_head = next;
- if (dlk == dlhrhs->dlh_tail)
- dlhlhs->dlh_tail = NULL;
- // break sibling links
- if (next != NULL)
- next->dlk_prev = NULL;
- if (prev != NULL)
- prev->dlk_next = NULL;
- // recount the nodes in both lists
- #if DLHCNT
- dlhlhs->dlh_cnt = 0;
- dlhinc(dlhrhs,-1);
- for (dlk_p cur = dlhlhs->dlh_head; cur != NULL; cur = cur->dlk_next) {
- dlhinc(dlhlhs,1);
- dlhinc(dlhrhs,-1);
- }
- #endif
- dlk->dlk_prev = NULL;
- dlk->dlk_next = NULL;
- dbgexec(1,dlhshow(dlhrhs,"dlhrhs/AFT"));
- dbgexec(1,dlhshow(dlhlhs,"dlhlhs/AFT"));
- dbgprt(1,"dlhcut: EXIT\n");
- }
- // dlkunlink -- remove item from list
- dlk_p
- dlkunlink(dlh_p dlh,dlk_p dlk)
- {
- dlk_p prev;
- dlk_p next;
- prev = dlk->dlk_prev;
- next = dlk->dlk_next;
- dlhinc(dlh,-1);
- if (prev != NULL)
- prev->dlk_next = next;
- else
- dlh->dlh_head = next;
- if (next != NULL)
- next->dlk_prev = prev;
- else
- dlh->dlh_tail = prev;
- dlk->dlk_prev = NULL;
- dlk->dlk_next = NULL;
- return dlk;
- }
- // dlhcnt -- calculate item count
- int
- dlhcnt(dlh_p dlh)
- {
- int cnt;
- #if DLHCNT
- cnt = dlh->dlh_cnt;
- #else
- cnt = 0;
- for (dlk_p dlk = dlh->dlh_head; dlk != NULL; dlk = dlk->dlk_next)
- cnt += 1;
- #endif
- return cnt;
- }
- // dlhshow -- output a list
- void
- dlhshow(dlh_p dlh,const char *reason)
- {
- dlk_p dlk;
- dlv_p dlv;
- _dbgprt("dlhshow: ENTER (from %s)\n",reason);
- dlv = dlh->dlh_dlv;
- for (dlk = dlh->dlh_head; dlk != NULL; dlk = dlk->dlk_next) {
- _dbgprt("dlhshow: OPT dlk_opt=%s\n",strtgb(opt_tgb,dlk->dlk_opt));
- dlv->dlv_show(dlk,reason);
- }
- _dbgprt("dlhshow: EXIT\n");
- }
- % parse.c
- // shpipe/parse -- line parser
- //
- // NOTE: split on "&" first before ";"
- #include <shpipe.h>
- static xcmd_p xcmd; // command list
- static xstr_p xstr; // current string under construction
- static int stopflg; // stop flag
- static int newflg; // 1=create new string
- #define GETC \
- if (stopflg) \
- break; \
- chr = *parsecur++; \
- if (chr == 0) { \
- stopflg = 1; \
- break; \
- }
- #define PEEKC(_chr) \
- if (stopflg) \
- break; \
- _chr = *parsecur
- // parseline -- line buffer parser
- xcmd_p
- parseline(char *buf)
- {
- int chr;
- int c2;
- parsebuf = buf;
- parsecur = buf;
- stopflg = 0;
- xcmd = xcmdnew();
- newflg = 1;
- xstr = NULL;
- while (1) {
- GETC;
- //xcmdshow(xcmd,"parseline");
- if ((chr == ' ') || (chr == '\t')) {
- newflg = 1;
- continue;
- }
- if (chr == '\\') {
- GETC;
- parsenew(chr,TOKWORD);
- continue;
- }
- switch (chr) {
- case '"':
- case '\'':
- parsequo(chr);
- continue;
- break;
- case '>':
- case '<':
- newflg = 2;
- parsenew(chr,TOKSEP);
- // handle "<<" or ">>"
- PEEKC(c2);
- if (c2 == chr) {
- xstraddchar(xstr,c2);
- GETC;
- }
- // handle ">&" or "<&"
- PEEKC(c2);
- if (c2 == '&') {
- xstraddchar(xstr,c2);
- GETC;
- }
- continue;
- break;
- case '`':
- case '&':
- case '|':
- case ';':
- newflg = 2;
- parsenew(chr,TOKSEP);
- continue;
- break;
- }
- parsenew(chr,TOKWORD);
- }
- return xcmd;
- }
- // parsenew -- add char
- void
- parsenew(int chr,int type)
- {
- if (newflg > 0) {
- newflg -= 1;
- xstr = xstrnew();
- xstr->xstr_type = type;
- xcmdpush(xcmd,xstr);
- }
- if (chr > 0)
- xstraddchar(xstr,chr);
- }
- // parsequo -- parse quoted string
- void
- parsequo(int quo)
- {
- int chr;
- int type;
- type = (quo == '"') ? TOKQUO2 : TOKQUO1;
- parsenew(-1,type);
- //xstraddchar(xstr,quo);
- while (1) {
- GETC;
- if (chr == quo)
- break;
- xstraddchar(xstr,chr);
- if (chr == '\\') {
- GETC;
- xstraddchar(xstr,chr);
- continue;
- }
- }
- }
- // tokmatch1 -- find a given token based on type and prefix value
- int
- tokmatch1(xstr_p xstr,int type,const char *src)
- {
- char *dst;
- int matchflg;
- do {
- matchflg = 0;
- if (type != 0) {
- if (xstr->xstr_type != type)
- break;
- }
- dst = xstrcstr(xstr);
- if (dst[0] != src[0])
- break;
- matchflg = 1;
- } while (0);
- return matchflg;
- }
- // tokmatch2 -- find a given token based on type and exact value
- int
- tokmatch2(xstr_p xstr,int type,const char *src)
- {
- char *dst;
- int matchflg;
- do {
- matchflg = 0;
- if (type != 0) {
- if (xstr->xstr_type != type)
- break;
- }
- dst = xstrcstr(xstr);
- if (strcmp(dst,src) != 0)
- break;
- matchflg = 1;
- } while (0);
- return matchflg;
- }
- // errprt -- show parsing error
- void
- errprt(xlst_p xlst,xcmd_p xcmd,xstr_p xstr,const char *fmt,...)
- {
- va_list ap;
- int idx;
- va_start(ap,fmt);
- vfprintf(stderr,fmt,ap);
- va_end(ap);
- ++errstop;
- if (xlst != NULL)
- xlst->xlst_opt |= OPTNOGO;
- if (xcmd != NULL)
- xcmd->xcmd_opt |= OPTNOGO;
- if (xstr != NULL) {
- fprintf(stderr,">>%s\n",xstr->xstr_bufptr);
- fputs(">>",stderr);
- for (idx = 0; idx < xstr->xstr_bufoff; ++idx)
- fputc('-',stderr);
- fputs("^\n",stderr);
- }
- }
- % pipe.c
- // shpipe/pipe -- pipeline control
- #include <shpipe.h>
- // cmdpipefork -- attach pipe to given command in pipeline
- int
- cmdpipefork(xcmd_p xcmd,u32 popt,int pno,xcmd_p prev)
- {
- xpipe_p xpipe;
- int pipeflg;
- pipeflg = 0;
- do {
- // command does not use this pipe end
- if ((xcmd->xcmd_opt & popt) == 0)
- break;
- // we need the correct pipe struct
- if (prev == NULL)
- break;
- xpipe = &prev->xcmd_xpipe;
- // duplicate the desired unit on the correct stdin/stdout
- dup2(xpipe->xpipe_fd[pno],pno);
- // get rid of the [now] extraneous unit
- CLOSEME(xpipe->xpipe_fd[pno]);
- // close the side we don't use
- pno = ! pno;
- CLOSEME(xpipe->xpipe_fd[pno]);
- pipeflg = 1;
- } while (0);
- return pipeflg;
- }
- // cmdpipeall -- set up piped job
- void
- cmdpipeall(xcmd_p xcmd)
- {
- u32 opt;
- xstr_p xstr;
- xlst_p xlst;
- dbgprt(1,"cmdpipeall: ENTER\n");
- dbgexec(1,xcmdshow(xcmd,"cmdpipeall"));
- // remember the OPTDETACH flag
- opt = xcmd->xcmd_opt;
- xlst = xlstnew();
- xlst->xlst_opt |= opt & OPTDETACH;
- // it's bad if we get "| cat"
- xstr = xcmd->xcmd_head;
- if (tokmatch2(xstr,TOKSEP,"|"))
- errprt(xlst,xcmd,xstr,"cmdpipe: malformed '|' at beginning\n");
- // it's bad if we get "cat |"
- xstr = xcmd->xcmd_tail;
- if (tokmatch2(xstr,TOKSEP,"|"))
- errprt(xlst,xcmd,xstr,"cmdpipe: malformed '|' at end\n");
- do {
- if (errstop)
- break;
- cmdsplit(xlst,xcmd,TOKSEP,"|",0);
- // mark all pipe sub-commands as having both input and output pipes
- for (xcmd = xlst->xlst_head; xcmd != NULL; xcmd = xcmd->xcmd_next) {
- xcmd->xcmd_opt |= OPTIPIPE;
- xcmd->xcmd_opt |= OPTOPIPE;
- }
- // first command of pipeline has no input pipe
- xcmd = xlst->xlst_head;
- xcmd->xcmd_opt &= ~OPTIPIPE;
- // last command of pipeline has no output pipe
- xcmd = xlst->xlst_tail;
- xcmd->xcmd_opt &= ~OPTOPIPE;
- // kick off the parts of the pipe
- for (xcmd = xlst->xlst_head; xcmd != NULL; xcmd = xcmd->xcmd_next) {
- if (errstop)
- break;
- cmdredall(xcmd);
- if (xcmd->xcmd_opt & OPTNOGO) {
- xlst->xlst_opt |= OPTNOGO;
- break;
- }
- }
- // don't wait if entire pipeline is detached
- if (opt & OPTDETACH)
- break;
- // wait for pipeline to complete
- cmdpipewait(xlst);
- } while (0);
- xlstfree(xlst);
- dbgprt(1,"cmdpipeall: EXIT\n");
- }
- // cmdpipewait -- wait for pipeline to complete
- void
- cmdpipewait(xlst_p xlst)
- {
- xcmd_p xcmd;
- int expcnt;
- pid_t pid;
- int status;
- int stage;
- dbgprt(1,"cmdpipewait: ENTER\n");
- // get number of _active_ pipe stages
- expcnt = 0;
- for (xcmd = xlst->xlst_head; xcmd != NULL; xcmd = xcmd->xcmd_next) {
- if (xcmd->xcmd_pid > 0)
- expcnt += 1;
- }
- dbgprt(1,"cmdpipewait: EXPCNT expcnt=%d\n",expcnt);
- while (expcnt > 0) {
- pid = waitpid(0,&status,0);
- if (pid < 0)
- break;
- dbgprt(1,"cmdpipewait: WAITPID status=%8.8X pid=%d\n",status,pid);
- // find match for just completed process
- stage = -1;
- for (xcmd = xlst->xlst_head; xcmd != NULL; xcmd = xcmd->xcmd_next) {
- ++stage;
- if (xcmd->xcmd_pid == pid) {
- dbgprt(1,"cmdpipewait: MATCH stage=%d\n",stage);
- expcnt -= 1;
- xcmd->xcmd_status = status;
- xcmd->xcmd_opt |= OPTDONE;
- xcmd->xcmd_pid = -1;
- break;
- }
- }
- }
- dbgprt(1,"cmdpipewait: EXIT\n");
- }
- % red.c
- // shpipe/red -- redirection and fork/exec control
- #include <shpipe.h>
- // cmdredall -- strip and setup redirections and fork/exec job
- void
- cmdredall(xcmd_p xcmd)
- {
- dbgprt(1,"cmdredall: ENTER\n");
- dbgexec(1,xcmdshow(xcmd,"cmdredall"));
- do {
- // split off redirections
- cmdredzone(xcmd);
- if (errstop)
- break;
- // open the units
- cmdredopen(xcmd);
- if (errstop)
- break;
- // fork job
- cmdredfork(xcmd);
- } while (0);
- dbgprt(1,"cmdredall: EXIT\n");
- }
- // cmdredzone -- strip and setup redirections
- void
- cmdredzone(xcmd_p xcmd)
- {
- int redno;
- redir_p red;
- char *sep;
- xstr_p xstr;
- u32 popt;
- dbgprt(1,"cmdredzone: ENTER\n");
- popt = 0;
- // split off redirections
- for (redno = 0; redno <= 1; ++redno) {
- if (xcmd->xcmd_opt & OPTNOGO)
- break;
- red = &xcmd->xcmd_redir[redno];
- switch (redno) {
- case 0:
- sep = "<";
- popt = OPTIPIPE;
- break;
- case 1:
- sep = ">";
- popt = OPTOPIPE;
- break;
- default:
- popt = 0;
- break;
- }
- // find the separater
- red->red_sep = xcmdfind1(xcmd,TOKSEP,sep);
- if (red->red_sep == NULL)
- continue;
- // get the filename
- red->red_file = red->red_sep->xstr_next;
- if (red->red_file == NULL) {
- errprt(NULL,xcmd,red->red_sep,
- "cmdredzone: missing filename for '%s'\n",sep);
- break;
- }
- // remove them from the command arguments
- xcmdunlink(xcmd,red->red_sep);
- xcmdunlink(xcmd,red->red_file);
- // check for errors
- xstr = xcmdfind1(xcmd,TOKSEP,sep);
- if (xstr != NULL) {
- errprt(NULL,xcmd,xstr,
- "cmdredzone: duplicate redirection '%s'\n",sep);
- break;
- }
- // check for overlap with pipe
- if (xcmd->xcmd_opt & popt) {
- errprt(NULL,xcmd,xstr,"cmdredzone: pipe overlap '%s'\n",sep);
- break;
- }
- }
- do {
- if (xcmd->xcmd_opt & OPTNOGO)
- break;
- // no child arguments
- if (xcmd->xcmd_head == NULL) {
- errprt(NULL,xcmd,NULL,
- "cmdredzone: no command after redirections\n");
- break;
- }
- } while (0);
- dbgprt(1,"cmdredzone: EXIT\n");
- }
- // cmdredopen -- open redirection units in parent
- void
- cmdredopen(xcmd_p xcmd)
- {
- int redno;
- redir_p red;
- char *sep;
- char *file;
- int opt;
- // we open the units in the parent so we can abort _without_ forking a child
- // if the unit open fails
- dbgprt(1,"cmdredopen: ENTER\n");
- // open the units
- for (redno = 0; redno <= 1; ++redno) {
- if (xcmd->xcmd_opt & OPTNOGO)
- break;
- red = &xcmd->xcmd_redir[redno];
- if (red->red_file == NULL)
- continue;
- file = xstrcstr(red->red_file);
- sep = xstrcstr(red->red_sep);
- switch (redno) {
- case 0: // open stdin
- if (xcmd->xcmd_opt & OPTIPIPE)
- continue;
- red->red_fd = open(file,O_RDONLY);
- break;
- case 1: // open stdout
- if (xcmd->xcmd_opt & OPTIPIPE)
- continue;
- opt = O_WRONLY | O_CREAT;
- if (sep[1] == '>')
- opt |= O_APPEND;
- red->red_fd = open(file,opt,0644);
- break;
- }
- dbgprt(1,"cmdredzone: OPEN redno=%d red_fd=%d file='%s'\n",
- redno,red->red_fd,file);
- if (red->red_fd < 0)
- errprt(NULL,xcmd,red->red_file,
- "cmdredzone: unable to open '%s' -- %s\n",
- file,strerror(errno));
- }
- dbgprt(1,"cmdredopen: EXIT\n");
- }
- // cmdredfork -- fork job
- void
- cmdredfork(xcmd_p xcmd)
- {
- int redno;
- redir_p red;
- int pipeflg;
- xpipe_p xpipe;
- pid_t pid;
- char *argv[SHANYMAX];
- dbgprt(1,"cmdredfork: ENTER\n");
- // create output pipe for us [and input side for next command in chain]
- if (xcmd->xcmd_opt & OPTOPIPE) {
- xpipe = &xcmd->xcmd_xpipe;
- pipe(xpipe->xpipe_fd);
- dbgprt(1,"cmdredfork: MKPIPE %d/%d\n",
- xpipe->xpipe_fd[0],xpipe->xpipe_fd[1]);
- }
- pid = fork();
- xcmd->xcmd_pid = pid;
- switch (pid) {
- case 0: // child
- for (redno = 0; redno <= 1; ++redno) {
- // attach pipe units
- switch (redno) {
- case 0:
- pipeflg = cmdpipefork(xcmd,OPTIPIPE,XPIPE_READ,
- xcmd->xcmd_prev);
- break;
- case 1:
- pipeflg = cmdpipefork(xcmd,OPTOPIPE,XPIPE_WRITE,xcmd);
- break;
- default:
- pipeflg = 0;
- break;
- }
- if (pipeflg)
- continue;
- // do we have a redirection?
- red = &xcmd->xcmd_redir[redno];
- if (red->red_file == NULL)
- continue;
- // attach the redirection
- dup2(red->red_fd,redno);
- CLOSEME(red->red_fd);
- }
- // get arguments in format needed by execvp
- xcmdargv(xcmd,argv);
- // execute the child program
- execvp(argv[0],argv);
- sysfault("cmdredfork: exec error on '%s' -- %s\n",
- argv[0],strerror(errno));
- break;
- case -1: // fork error
- /* unlikely but possible if hit a limit */
- errprt(NULL,xcmd,NULL,"ERROR can't create child process!\n");
- cmdredclose(xcmd,1);
- break;
- default: // parent
- dbgprt(1,"cmdredfork: FORK pid=%d\n",pid);
- cmdredclose(xcmd,0);
- // don't wait for detached jobs
- if (xcmd->xcmd_opt & OPTDETACH)
- break;
- // don't wait for piped jobs here -- we must finish constructing the
- // pipeline
- if (xcmd->xcmd_opt & (OPTIPIPE | OPTOPIPE))
- break;
- waitpid(pid,&xcmd->xcmd_status,0);
- xcmd->xcmd_opt |= OPTDONE;
- break;
- }
- dbgprt(1,"cmdredfork: EXIT\n");
- }
- // cmdredclose -- close redirections and pipe units in parent
- void
- cmdredclose(xcmd_p xcmd,int errflg)
- {
- int redno;
- xpipe_p xpipe;
- xcmd_p prev;
- redir_p red;
- dbgprt(1,"cmdredclose: ENTER errflg=%d\n",errflg);
- // we get called by parent after fork to clean up units that are no longer
- // needed and would gunk up a later stage child in a pipeline
- // we have to keep the read side of the pipe for the _next_ stage [unless
- // there's been a fatal error]
- xpipe = &xcmd->xcmd_xpipe;
- if (errflg)
- CLOSEME(xpipe->xpipe_fd[XPIPE_READ]);
- CLOSEME(xpipe->xpipe_fd[XPIPE_WRITE]);
- // close pipe units from prior stage [if we have one]
- prev = xcmd->xcmd_prev;
- if (prev != NULL) {
- xpipe = &xcmd->xcmd_xpipe;
- CLOSEME(xpipe->xpipe_fd[XPIPE_READ]);
- CLOSEME(xpipe->xpipe_fd[XPIPE_WRITE]);
- }
- // close all our redirections
- for (redno = 0; redno <= 1; ++redno) {
- red = &xcmd->xcmd_redir[redno];
- CLOSEME(red->red_fd);
- XSTRFREE(red->red_sep);
- XSTRFREE(red->red_file);
- }
- dbgprt(1,"cmdredclose: EXIT\n");
- }
- % shpipe.c
- // shpipe/shpipe -- shell with pipes
- #define _SHPIPE_GLO_
- #include <shpipe.h>
- char *prompt = "% ";
- // main -- main program
- int
- main(int argc,char **argv)
- {
- pid_t pid;
- char line[SHANYMAX];
- char *cp;
- char *ifile;
- int status;
- int promptflg;
- xcmd_p xcmd;
- xlst_p xlst;
- --argc;
- ++argv;
- for (; argc > 0; --argc, ++argv) {
- cp = *argv;
- if (*cp != '-')
- break;
- switch (cp[1]) {
- case 'd':
- opt_debug = 1;
- break;
- }
- }
- xfintop = stdin;
- ifile = NULL;
- pidtop = getpid();
- if (argc > 0) {
- ifile = *argv;
- xfintop = fopen(ifile,"r");
- if (xfintop == NULL)
- sysfault("main: unable to open '%s' -- %s\n",
- ifile,strerror(errno));
- }
- parseinfo.xstr_file = ifile;
- //int joke = open("/dev/null",O_RDONLY);
- xfdget(xfdchk_std);
- //close(joke);
- //signal(SIGINT, SIG_IGN);
- promptflg = (ifile == NULL);
- while (1) {
- sysmchk();
- xfdchk(xfdchk_std);
- if (promptflg) {
- promptflg = 0;
- fprintf(stderr,"%s",prompt);
- fflush(stderr);
- }
- // reap detached jobs
- while (1) {
- pid = waitpid(0,&status,WNOHANG);
- if (pid <= 0)
- break;
- }
- // abort script on errors
- if ((ifile != NULL) && errstop)
- break;
- errstop = 0;
- // get new input line
- if (ifile != NULL)
- parseinfo.xstr_fpos = ftell(xfintop);
- cp = fgets(line,sizeof(line),xfintop);
- // we can be interrupted if we enable SIGCHLD (i.e. we can keep things
- // tidy even if we wait for hours for user input)
- if (cp == NULL) {
- fprintf(stderr,"main: DEBUG_CAE/GETS -- %s\n",strerror(errno));
- if (errno != EINTR)
- break;
- continue;
- }
- promptflg = (ifile == NULL);
- ++parseinfo.xstr_lno;
- cp = strchr(line,'\n');
- if (cp != NULL)
- *cp = 0;
- if (ifile != NULL)
- dbgprt(1,"main: LINE '%s'\n",line);
- xcmd = parseline(line);
- dbgexec(1,xcmdshow(xcmd,"parseline"));
- xlst = xlstnew();
- cmdsplit(xlst,xcmd,TOKSEP,";",OPTLOCK);
- // do single commands separated by semicolons
- for (xcmd = xlst->xlst_head; xcmd != NULL; xcmd = xcmd->xcmd_next) {
- cmdsemi(xcmd);
- xcmd->xcmd_opt &= ~OPTLOCK;
- }
- xlstfree(xlst);
- }
- if (parseinfo.xstr_file != NULL)
- fclose(xfintop);
- return 0;
- }
- // cmdsemi -- run a job
- void
- cmdsemi(xcmd_p xcmd)
- {
- xstr_p xstr;
- xcmd->xcmd_opt &= ~(OPTNOGO | OPTDETACH);
- // decide if we want a detached job
- do {
- xstr = xcmdfind2(xcmd,TOKSEP,"&");
- if (xstr == NULL)
- break;
- xcmd->xcmd_opt |= OPTDETACH;
- // the token _must_ be the last or we can't really divine intent too
- // well
- if (xstr->xstr_next != NULL) {
- errprt(NULL,xcmd,xstr,
- "cmdsemi: found '&' in middle of command\n");
- break;
- }
- // just get rid of it
- xcmdunlink(xcmd,xstr);
- xstrfree(xstr);
- } while (0);
- // decide if we have pipes
- // do this early to allow the simple [non-pipe] case to go quickly
- do {
- if (xcmd->xcmd_opt & OPTNOGO)
- break;
- xstr = xcmdfind2(xcmd,TOKSEP,"|");
- if (xstr != NULL)
- cmdpipeall(xcmd);
- else
- cmdredall(xcmd);
- } while (0);
- }
- // cmdsplit -- split on token
- void
- cmdsplit(xlst_p xlst,xcmd_p xcmd,int type,char *sep,u32 opt)
- {
- xstr_p xstr;
- xcmd_p xcut;
- while (1) {
- xstr = xcmdfind2(xcmd,type,sep);
- if (xstr == NULL)
- break;
- xcut = xcmdcut(xcmd,xstr);
- xcut->xcmd_opt |= opt;
- xlstpush(xlst,xcut);
- xstrfree(xstr);
- }
- if (xcmd->xcmd_head != NULL) {
- xcmd->xcmd_opt |= opt;
- xlstpush(xlst,xcmd);
- }
- else
- xcmdfree(xcmd);
- }
- % shpipe.h
- // shpipe/shpipe.h -- shell pipe control
- #ifndef _shpipe_shpipe_h_
- #define _shpipe_shpipe_h_
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <unistd.h>
- #include <string.h>
- #include <errno.h>
- #include <signal.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #define SUPER_INLINE __attribute__((always_inline)) static inline
- #ifdef _SHPIPE_GLO_
- #define EXTRN_SHPIPE /**/
- #else
- #define EXTRN_SHPIPE extern
- #endif
- typedef unsigned char byte;
- typedef unsigned int u32;
- #define CAST(_typ,_val) \
- ((_typ) (_val))
- #define FWD(_typ) \
- struct _##_typ; \
- typedef struct _##_typ _typ##_t; \
- typedef _typ##_t *_typ##_p
- FWD(xstr);
- FWD(xpipe);
- FWD(redir);
- FWD(xcmd);
- FWD(xlst);
- #define SHANYMAX 300 // maximum for anything
- // bit mask operations
- #define BTVOFF(_bitno) ((_bitno) >> 3)
- #define BTVMSK(_bitno) (1u << ((_bitno) % 0x07))
- #define BTVLEN(_bitcnt) ((((_bitcnt) + 7) >> 3) << 3)
- #define BTVSET(_vec,_bitno) _vec[BTVOFF(_bitno)] |= BTVMSK(_bitno)
- #define BTVCLR(_vec,_bitno) _vec[BTVOFF(_bitno)] &= ~BTVMSK(_bitno)
- #ifndef DLHCNT
- #define DLHCNT 1
- #endif
- #ifndef XMEMCHK
- #define XMEMCHK 1
- #endif
- #if XMEMCHK
- #define syscalloc(_cnt,_len,_mag) _syscalloc(_cnt,_len,_mag,__FILE__,__LINE__)
- #define sysfree(_vp) _sysfree(_vp)
- #define sysmchk() _sysmchk()
- #else
- #define syscalloc(_cnt,_len,_mag) calloc(_cnt,_len)
- #define sysfree(_vp) free(_vp)
- #define sysmchk() /**/
- #endif
- #ifndef XFDCHK
- #define XFDCHK 1
- #endif
- #define XFDMAX 1024
- #if XFDCHK
- #define xfdget(_vec) _xfdget(_vec)
- #define xfdchk(_vec) _xfdchk(_vec)
- #else
- #define xfdget(_vec) /**/
- #define xfdchk(_vec) /**/
- #endif
- pid_t pidtop; // top/master process id
- FILE *xfintop; // top input stream
- EXTRN_SHPIPE byte xfdchk_std[BTVLEN(XFDMAX)];
- // magic numbers
- typedef enum {
- SYSMAGIC_XSTR = 0xDEADBE01,
- SYSMAGIC_XCMD = 0xDEADBE02,
- SYSMAGIC_XLST = 0xDEADBE03,
- SYSMAGIC_ARGV = 0xDEADBE04,
- } sysmagic_t;
- // allocation control
- FWD(xmem);
- struct _xmem {
- sysmagic_t xmem_magic; // magic number
- xmem_p xmem_next; // linkage
- const char *xmem_file; // file
- int xmem_lno; // line number
- //long xmem_rsvp;
- };
- EXTRN_SHPIPE xmem_p xmemall;
- EXTRN_SHPIPE int opt_debug;
- #define sysfault(_fmt...) \
- do { \
- fprintf(stderr,_fmt); \
- exit(1); \
- } while (0)
- #define dbgprt(_lvl,_fmt...) \
- do { \
- if (opt_debug) \
- _dbgprt(_fmt); \
- } while (0)
- #define _dbgprt(_fmt...) \
- fprintf(stderr,_fmt)
- #define dbgexec(_lvl,_expr) \
- do { \
- if (opt_debug) \
- _expr; \
- } while (0)
- #define OPTALL(_cmd) \
- _cmd(TOKSEP,"special separater") \
- _cmd(TOKQUO1,"single quoted string") \
- _cmd(TOKQUO2,"double quoted string") \
- _cmd(TOKWORD,"ordinary word") \
- _cmd(OPTNOGO,"error occurred") \
- _cmd(OPTDETACH,"detach job") \
- _cmd(OPTLOCK,"struct locked") \
- _cmd(OPTIPIPE,"input pipe") \
- _cmd(OPTOPIPE,"output pipe") \
- _cmd(OPTDONE,"command done")
- #define _OPTDEF(_sym,_reason) \
- _##_sym,
- enum {
- OPTALL(_OPTDEF)
- };
- #define _OPTMSK(_sym,_reason) \
- _sym = (1 << _##_sym),
- enum {
- OPTALL(_OPTMSK)
- };
- // option/symbol display control
- FWD(tgb);
- struct _tgb {
- const char *tgb_tag; // symbol name
- u32 tgb_val; // symbol value
- const char *tgb_reason; // symbol explanation
- };
- #define TGBEOT \
- { .tgb_tag = NULL }
- #define TGBMORE(_tgb) \
- _tgb != NULL
- #define _OPTTGB(_sym,_reason) \
- { .tgb_tag = #_sym, .tgb_val = _sym, .tgb_reason = _reason },
- #ifdef _SHPIPE_GLO_
- tgb_t opt_tgb[] = {
- OPTALL(_OPTTGB)
- TGBEOT
- };
- #else
- extern tgb_t opt_tgb[];
- #endif
- FWD(dlh);
- FWD(dlk);
- FWD(dlv);
- #define DLKDEF(_typ) \
- sysmagic_t _typ##_magic; /* magic number */ \
- u32 _typ##_opt; /* options */ \
- _typ##_p _typ##_prev; /* pointer to previous item in list */ \
- _typ##_p _typ##_next /* pointer to next item in list */
- #define DLKOF(_ptr) \
- CAST(dlk_p,_ptr)
- #define DLHDEF(_pre,_typ) \
- _typ##_p _pre##head; /* head of list */ \
- _typ##_p _pre##tail; /* tail of list */ \
- dlv_p _pre##dlv; /* virtual function table pointer */ \
- int _pre##cnt; /* number of items in list */
- #define DLHOF(_ptr,_pre) \
- CAST(dlh_p,&_ptr->_pre##head)
- // doubly linked list virtual function table
- struct _dlv {
- void (*dlv_free)(dlk_p dlk); // free the item
- void (*dlv_show)(dlk_p dlk,const char *reason); // show the item
- };
- // doubly linked list item
- struct _dlk {
- DLKDEF(dlk);
- };
- // doubly linked list header
- struct _dlh {
- DLHDEF(dlh_,dlk);
- };
- // string buffer
- struct _xstr {
- DLKDEF(xstr); // linkage
- u32 xstr_type; // string type
- size_t xstr_maxlen; // maximum space in string buffer
- char *xstr_lhs; // pointer to start of string
- char *xstr_rhs; // pointer to current string append
- char *xstr_file; // input file
- long xstr_fpos; // input file position
- int xstr_lno; // input file line number
- char *xstr_bufptr; // pointer to buffer
- long xstr_bufoff; // beginning buffer offset
- };
- // pipe control
- struct _xpipe {
- int xpipe_fd[2]; // pipe units
- };
- #define XPIPE_READ 0 // read/input side of pipe
- #define XPIPE_WRITE 1 // write/output side of pipe
- // redirection control
- struct _redir {
- xstr_p red_sep; // separater
- xstr_p red_file; // filename
- int red_fd; // open file unit
- };
- // close file descriptor
- #define CLOSEME(_fd) \
- _fd = closeme(_fd,__FILE__,__LINE__)
- #define XSTRFREE(_xstr) \
- _xstr = xstrfree(_xstr)
- // command control
- struct _xcmd {
- DLKDEF(xcmd); // linkage
- DLHDEF(xcmd_,xstr); // list of strings
- redir_t xcmd_redir[2]; // redirection control
- xpipe_t xcmd_xpipe; // output side pipe
- pid_t xcmd_pid; // process id
- int xcmd_status; // completion status
- };
- #define XCMD_DLHOF(_xcmd) \
- DLHOF(_xcmd,xcmd_)
- // command list
- struct _xlst {
- DLKDEF(xlst); // linkage
- DLHDEF(xlst_,xcmd); // list of commands
- };
- #define XLST_DLHOF(_xlst) \
- DLHOF(_xlst,xlst_)
- EXTRN_SHPIPE xstr_t parseinfo; // information
- EXTRN_SHPIPE char *parsebuf; // current buffer
- EXTRN_SHPIPE char *parsecur; // current offset
- EXTRN_SHPIPE int errstop; // errors
- #include <shpipe.proto>
- // closeme -- close a unit
- SUPER_INLINE int
- closeme(int fd,const char *file,int lno)
- {
- #if XFDCHK
- fd = _closeme(fd,file,lno);
- #else
- do {
- if (fd < 0)
- break;
- dbgprt(1,"closeme: CLOSE fd=%d file='%s' lno=%d\n",
- fd,file,lno);
- close(fd);
- _fd = -1;
- } while (0)
- #endif
- return fd;
- }
- // btvget -- fetch bit vector value
- SUPER_INLINE byte
- btvget(const byte *vec,int bitno)
- {
- vec += BTVOFF(bitno);
- return *vec & BTVMSK(bitno);
- }
- // btvset -- set bit vector value
- SUPER_INLINE void
- btvset(byte *vec,int bitno,int val)
- {
- byte msk;
- vec += BTVOFF(bitno);
- msk = BTVMSK(bitno);
- if (val)
- *vec |= msk;
- else
- *vec &= ~msk;
- }
- // dlhinc -- increment/decrement list count
- SUPER_INLINE void
- dlhinc(dlh_p dlh,int inc)
- {
- #if DLHCNT
- dlh->dlh_cnt += inc;
- #endif
- }
- // xstrcstr -- get the "c string" value
- SUPER_INLINE char *
- xstrcstr(xstr_p xstr)
- {
- return xstr->xstr_lhs;
- }
- // xcmd virtual function table
- #ifdef _SHPIPE_GLO_
- dlv_t xcmd_dlv = {
- .dlv_free = xstrfree_dlv,
- .dlv_show = xstrshow_dlv,
- };
- #else
- extern dlv_t xcmd_dlv;
- #endif
- // xlst virtual function table
- #ifdef _SHPIPE_GLO_
- dlv_t xlst_dlv = {
- .dlv_free = xcmdfree_dlv,
- .dlv_show = xcmdshow_dlv,
- };
- #else
- extern dlv_t xlst_dlv;
- #endif
- #endif
- % shredir.c
- // shpipe/shredir -- original answer
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <errno.h>
- #include <signal.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- char *prompt = "% ";
- int
- main()
- {
- int pid;
- //int child_pid;
- char line[81];
- char *token;
- char *separator = " \t\n";
- char **args;
- char **args2;
- char *cp;
- char *ifile;
- char *ofile;
- int i;
- int j;
- int err;
- //int check;
- //char history[90];
- //typedef void (*sighandler_t) (int);
- args = malloc(80 * sizeof(char *));
- args2 = malloc(80 * sizeof(char *));
- //signal(SIGINT, SIG_IGN);
- while (1) {
- fprintf(stderr, "%s", prompt);
- fflush(stderr);
- if (fgets(line, 80, stdin) == NULL)
- break;
- // split up the line
- i = 0;
- while (1) {
- token = strtok((i == 0) ? line : NULL, separator);
- if (token == NULL)
- break;
- args[i++] = token; /* build command array */
- }
- args[i] = NULL;
- if (i == 0)
- continue;
- // assume no redirections
- ofile = NULL;
- ifile = NULL;
- // split off the redirections
- j = 0;
- i = 0;
- err = 0;
- while (1) {
- cp = args[i++];
- if (cp == NULL)
- break;
- switch (*cp) {
- case '<':
- if (cp[1] == 0)
- cp = args[i++];
- else
- ++cp;
- ifile = cp;
- if (cp == NULL)
- err = 1;
- else
- if (cp[0] == 0)
- err = 1;
- break;
- case '>':
- if (cp[1] == 0)
- cp = args[i++];
- else
- ++cp;
- ofile = cp;
- if (cp == NULL)
- err = 1;
- else
- if (cp[0] == 0)
- err = 1;
- break;
- default:
- args2[j++] = cp;
- break;
- }
- }
- args2[j] = NULL;
- // we got something like "cat <"
- if (err)
- continue;
- // no child arguments
- if (j == 0)
- continue;
- switch (pid = fork()) {
- case 0:
- // open stdin
- if (ifile != NULL) {
- int fd = open(ifile, O_RDONLY);
- if (dup2(fd, STDIN_FILENO) == -1) {
- fprintf(stderr, "dup2 failed");
- }
- close(fd);
- }
- // trying to get this to work
- // NOTE: now it works :-)
- // open stdout
- if (ofile != NULL) {
- // args[1] = NULL;
- int fd2;
- //printf("PLEASE WORK");
- if ((fd2 = open(ofile, O_WRONLY | O_CREAT, 0644)) < 0) {
- perror("couldn't open output file.");
- exit(0);
- }
- // args+=2;
- printf("okay");
- dup2(fd2, STDOUT_FILENO);
- close(fd2);
- }
- execvp(args2[0], args2); /* child */
- signal(SIGINT, SIG_DFL);
- fprintf(stderr, "ERROR %s no such program\n", line);
- exit(1);
- break;
- case -1:
- /* unlikely but possible if hit a limit */
- fprintf(stderr, "ERROR can't create child process!\n");
- break;
- default:
- //printf("am I here");
- wait(NULL);
- //waitpid(pid, 0, 0);
- }
- }
- exit(0);
- }
- % str.c
- // shpipe/str -- string functions
- #include <shpipe.h>
- #define TMPMAX 20
- static int tmpidx;
- static char tmpbuf[TMPMAX][SHANYMAX];
- // strtmp -- temporary persistent string buffer
- char *
- strtmp(void)
- {
- char *bf;
- bf = tmpbuf[tmpidx];
- if (++tmpidx >= TMPMAX)
- tmpidx = 0;
- *bf = 0;
- return bf;
- }
- // strtgb -- display option mask
- char *
- strtgb(tgb_p tgb,u32 opt)
- {
- char *bp;
- const char *sep;
- char *bf;
- bf = strtmp();
- bp = bf;
- *bp++ = '(';
- sep = "";
- for (; TGBMORE(tgb); ++tgb) {
- if (opt & tgb->tgb_val) {
- bp += sprintf(bp,"%s%s",sep,tgb->tgb_tag);
- sep = " ";
- }
- }
- *bp++ = ')';
- *bp = 0;
- return bf;
- }
- % sysf.c
- // shpipe/sysf -- file descriptor leak detection
- #include <shpipe.h>
- // _closeme -- close a unit
- int
- _closeme(int fd,const char *file,int lno)
- {
- int err;
- do {
- if (fd < 0)
- break;
- dbgprt(1,"closeme: CLOSE fd=%d file='%s' lno=%d\n",
- fd,file,lno);
- err = 0;
- if (fd == fileno(xfintop))
- err |= 1;
- if (fd == 0)
- err |= 2;
- #if 0
- if (fd == 3)
- err |= 4;
- #endif
- if (err)
- sysfault("_closeme: fault -- fd=%d file='%s' lno=%d\n",fd,file,lno);
- close(fd);
- fd = -1;
- } while (0);
- return fd;
- }
- // _xfdget -- get vector of currently open file descriptors
- void
- _xfdget(byte *vec)
- {
- int fd;
- int err;
- for (fd = 0; fd < XFDMAX; ++fd) {
- err = fcntl(fd,F_GETFD);
- err = (err >= 0);
- btvset(vec,fd,err);
- }
- }
- // _xfdchk -- get vector of currently open file descriptors
- void
- _xfdchk(byte *stdvec)
- {
- byte stdval;
- byte curval;
- int fd;
- int err;
- byte curvec[BTVLEN(XFDMAX)];
- _xfdget(curvec);
- err = 0;
- for (fd = 0; fd < XFDMAX; ++fd) {
- stdval = btvget(stdvec,fd);
- stdval = stdval ? 1 : 0;
- curval = btvget(curvec,fd);
- curval = curval ? 1 : 0;
- if (curval != stdval) {
- err = 1;
- fprintf(stderr,"xfdchk: mismatch -- fd=%d stdval=%d curval=%d\n",
- fd,stdval,curval);
- }
- }
- if (err)
- sysfault("xfdchk: aborting\n");
- }
- % sysm.c
- // shpipe/sysm -- memory leak detection
- #include <shpipe.h>
- // _syscalloc -- get new list
- void *
- _syscalloc(size_t cnt,size_t len,sysmagic_t magno,const char *file,int lno)
- {
- xmem_p xmem;
- void *vp;
- if ((sizeof(xmem_t) % 8) != 0)
- sysfault("_syscalloc: xmem_t sizeof fault -- %ld\n",
- (long) sizeof(xmem_t));
- // get total size [including our control struct]
- len *= cnt;
- len += sizeof(xmem_t);
- // allocate and clear
- xmem = malloc(len);
- memset(xmem,0,len);
- // link us into the global list
- xmem->xmem_next = xmemall;
- xmemall = xmem;
- // say who did the allocation
- xmem->xmem_magic = magno;
- xmem->xmem_file = file;
- xmem->xmem_lno = lno;
- // get the visible pointer
- vp = xmem;
- vp += sizeof(xmem_t);
- return vp;
- }
- // _sysfree -- free list
- void
- _sysfree(void *vp)
- {
- xmem_p xmem;
- xmem_p cur;
- xmem_p prev;
- // get our internal pointer
- vp -= sizeof(xmem_t);
- xmem = vp;
- // find our place in the global list
- prev = NULL;
- for (cur = xmemall; cur != NULL; prev = cur, cur = cur->xmem_next) {
- if (cur == xmem)
- break;
- }
- // remove us from the list
- if (prev != NULL)
- prev->xmem_next = xmem->xmem_next;
- else
- xmemall = xmem->xmem_next;
- // release the memory
- free(xmem);
- }
- // _sysmchk -- check memory
- void
- _sysmchk(void)
- {
- xmem_p xmem;
- void *vp;
- for (xmem = xmemall; xmem != NULL; xmem = xmem->xmem_next) {
- vp = xmem;
- vp += sizeof(xmem_t);
- _dbgprt("sysmchk: vp=%p xmem_file='%s' xmem_lno=%d\n",
- vp,xmem->xmem_file,xmem->xmem_lno);
- switch (xmem->xmem_magic) {
- case SYSMAGIC_XSTR:
- xstrshow(vp);
- break;
- case SYSMAGIC_XCMD:
- xcmdshow(vp,"sysmchk");
- break;
- case SYSMAGIC_XLST:
- xlstshow(vp,"sysmchk");
- break;
- case SYSMAGIC_ARGV:
- break;
- }
- }
- if (xmemall != NULL)
- sysfault("_sysmchk: aborting\n");
- }
- % xcmd.c
- // shpipe/xcmd -- "smart" list "class" for C
- #include <shpipe.h>
- // xcmdnew -- get new list
- xcmd_p
- xcmdnew(void)
- {
- int redno;
- dlh_p dlh;
- xpipe_p xpipe;
- xcmd_p xcmd;
- xcmd = syscalloc(1,sizeof(xcmd_t),SYSMAGIC_XCMD);
- for (redno = 0; redno <= 1; ++redno)
- xcmd->xcmd_redir[redno].red_fd = -1;
- xpipe = &xcmd->xcmd_xpipe;
- for (redno = 0; redno <= 1; ++redno)
- xpipe->xpipe_fd[redno] = -1;
- dlh = XCMD_DLHOF(xcmd);
- dlh->dlh_dlv = &xcmd_dlv;
- return xcmd;
- }
- // xcmdfree -- free list
- xcmd_p
- xcmdfree(xcmd_p xcmd)
- {
- xpipe_p xpipe;
- do {
- if (xcmd == NULL)
- break;
- if (xcmd->xcmd_opt & OPTLOCK)
- break;
- xpipe = &xcmd->xcmd_xpipe;
- xcmd->xcmd_opt &= ~OPTIPIPE;
- CLOSEME(xpipe->xpipe_fd[XPIPE_READ]);
- xcmd->xcmd_opt &= ~OPTOPIPE;
- CLOSEME(xpipe->xpipe_fd[XPIPE_WRITE]);
- _dlhfree(XCMD_DLHOF(xcmd));
- sysfree(xcmd);
- xcmd = NULL;
- } while (0);
- return xcmd;
- }
- // xcmdargv -- convert list to argv
- char **
- xcmdargv(xcmd_p xcmd,char **argv)
- // argv -- flat list pointer (null means allocate)
- {
- char **av;
- int cnt;
- xstr_p xstr;
- if (argv == NULL) {
- cnt = xcmdcnt(xcmd);
- argv = syscalloc(cnt + 1,sizeof(char *),SYSMAGIC_ARGV);
- }
- av = argv;
- for (xstr = xcmd->xcmd_head; xstr != NULL; xstr = xstr->xstr_next, ++av)
- *av = xstrcstr(xstr);
- *av = NULL;
- return argv;
- }
- // xcmdpush -- append string to end of list
- xstr_p
- xcmdpush(xcmd_p xcmd,xstr_p xstr)
- {
- dlkpush(XCMD_DLHOF(xcmd),DLKOF(xstr));
- return xstr;
- }
- // xcmdfind1 -- find a given token based on type and prefix value
- xstr_p
- xcmdfind1(xcmd_p xcmd,int type,const char *src)
- {
- xstr_p xstr;
- for (xstr = xcmd->xcmd_head; xstr != NULL; xstr = xstr->xstr_next) {
- if (tokmatch1(xstr,type,src))
- break;
- }
- return xstr;
- }
- // xcmdfind2 -- find a given token based on type and exact value
- xstr_p
- xcmdfind2(xcmd_p xcmd,int type,const char *src)
- {
- xstr_p xstr;
- for (xstr = xcmd->xcmd_head; xstr != NULL; xstr = xstr->xstr_next) {
- if (tokmatch2(xstr,type,src))
- break;
- }
- return xstr;
- }
- // xcmdcut -- cut out entry and split list
- xcmd_p
- xcmdcut(xcmd_p xcmdrhs,xstr_p xstr)
- {
- xcmd_p xcmdlhs;
- xcmdlhs = xcmdnew();
- dlhcut(XCMD_DLHOF(xcmdlhs),XCMD_DLHOF(xcmdrhs),DLKOF(xstr));
- return xcmdlhs;
- }
- // xcmdunlink -- remove string from list
- xstr_p
- xcmdunlink(xcmd_p xcmd,xstr_p xstr)
- {
- dlkunlink(XCMD_DLHOF(xcmd),DLKOF(xstr));
- return xstr;
- }
- // xcmdcnt -- calculate string count
- int
- xcmdcnt(xcmd_p xcmd)
- {
- return dlhcnt(XCMD_DLHOF(xcmd));
- }
- // xcmdshow -- output a list
- void
- xcmdshow(xcmd_p xcmd,const char *reason)
- {
- dlhshow(XCMD_DLHOF(xcmd),reason);
- }
- // xcmdfree_dlv -- release string buffer data
- void
- xcmdfree_dlv(dlk_p dlk)
- {
- xcmdfree((xcmd_p) dlk);
- }
- // xcmdshow_dlv -- show data
- void
- xcmdshow_dlv(dlk_p dlk,const char *reason)
- {
- xcmdshow((xcmd_p) dlk,reason);
- }
- % xlst.c
- // shpipe/xlst -- "smart" list "class" for C
- #include <shpipe.h>
- // xlstnew -- get new list
- xlst_p
- xlstnew(void)
- {
- dlh_p dlh;
- xlst_p xlst;
- xlst = syscalloc(1,sizeof(xlst_t),SYSMAGIC_XLST);
- xlst->xlst_magic = SYSMAGIC_XLST;
- dlh = XLST_DLHOF(xlst);
- dlh->dlh_dlv = &xlst_dlv;
- return xlst;
- }
- // xlstfree -- free list
- xlst_p
- xlstfree(xlst_p xlst)
- {
- do {
- if (xlst == NULL)
- break;
- if (xlst->xlst_opt & OPTLOCK)
- break;
- _dlhfree(XLST_DLHOF(xlst));
- sysfree(xlst);
- xlst = NULL;
- } while (0);
- return xlst;
- }
- // xlstpush -- append string to end of list
- xcmd_p
- xlstpush(xlst_p xlst,xcmd_p xcmd)
- {
- dlkpush(XLST_DLHOF(xlst),DLKOF(xcmd));
- return xcmd;
- }
- // xlstcut -- cut out entry and split list
- xlst_p
- xlstcut(xlst_p xlstrhs,xcmd_p xcmd)
- {
- xlst_p xlstlhs;
- xlstlhs = xlstnew();
- dlhcut(XLST_DLHOF(xlstlhs),XLST_DLHOF(xlstrhs),DLKOF(xcmd));
- return xlstlhs;
- }
- // xlstunlink -- remove string from list
- xcmd_p
- xlstunlink(xlst_p xlst,xcmd_p xcmd)
- {
- dlkunlink(XLST_DLHOF(xlst),DLKOF(xcmd));
- return xcmd;
- }
- // xlstcnt -- calculate string count
- int
- xlstcnt(xlst_p xlst)
- {
- return dlhcnt(XLST_DLHOF(xlst));
- }
- // xlstshow -- output a list
- void
- xlstshow(xlst_p xlst,const char *reason)
- {
- dlhshow(XLST_DLHOF(xlst),reason);
- }
- % xstr.c
- // shpipe/xstr -- "smart" string "class" for C
- #include <shpipe.h>
- xstr_p xstrpool;
- // xstragain -- reset string buffer
- void
- xstragain(xstr_p xstr)
- {
- xstr->xstr_rhs = xstr->xstr_lhs;
- }
- // xstrnew -- allocate string buffer
- xstr_p
- xstrnew(void)
- {
- xstr_p xstr;
- do {
- xstr = xstrpool;
- if (xstr == NULL) {
- xstr = syscalloc(1,sizeof(xstr_t),SYSMAGIC_XSTR);
- xstr->xstr_magic = SYSMAGIC_XSTR;
- break;
- }
- xstrpool = xstr->xstr_next;
- xstragain(xstr);
- xstr->xstr_prev = NULL;
- xstr->xstr_next = NULL;
- } while (0);
- xstr->xstr_file = parseinfo.xstr_file;
- xstr->xstr_lno = parseinfo.xstr_lno;
- xstr->xstr_fpos = parseinfo.xstr_fpos;
- xstr->xstr_bufptr = parsebuf;
- xstr->xstr_bufoff = (parsecur - parsebuf) - 1;
- xstr->xstr_type = 0;
- xstr->xstr_opt = 0;
- return xstr;
- }
- // xstrgrow -- grow string buffer
- void
- xstrgrow(xstr_p xstr,size_t needlen)
- {
- size_t curlen;
- size_t newlen;
- char *lhs;
- lhs = xstr->xstr_lhs;
- // get amount we're currently using
- curlen = xstr->xstr_rhs - lhs;
- // get amount we'll need after adding the whatever
- newlen = curlen + needlen + 1;
- // allocate more if we need it
- if ((newlen + 1) >= xstr->xstr_maxlen) {
- // allocate what we'll need plus a bit more so we're not called on
- // each add operation
- xstr->xstr_maxlen = newlen + 100;
- // get more memory
- lhs = realloc(lhs,xstr->xstr_maxlen);
- xstr->xstr_lhs = lhs;
- // adjust the append pointer
- xstr->xstr_rhs = lhs + curlen;
- }
- }
- // xstraddchar -- add character to string
- void
- xstraddchar(xstr_p xstr,int chr)
- {
- // get more space in string buffer if we need it
- xstrgrow(xstr,1);
- // add the character
- *xstr->xstr_rhs++ = chr;
- // maintain the sentinel/EOS as we go along
- *xstr->xstr_rhs = 0;
- }
- // xstraddstr -- add string to string
- void
- xstraddstr(xstr_p xstr,const char *str)
- {
- size_t len;
- len = strlen(str);
- // get more space in string buffer if we need it
- xstrgrow(xstr,len);
- // add the string
- memcpy(xstr->xstr_rhs,str,len);
- xstr->xstr_rhs += len;
- // maintain the sentinel/EOS as we go along
- *xstr->xstr_rhs = 0;
- }
- // xstrclean -- clean the pool
- void
- xstrclean(void)
- {
- xstr_p cur;
- xstr_p next;
- for (cur = xstrpool; cur != NULL; cur = next) {
- next = cur->xstr_next;
- _xstrfree(cur);
- }
- xstrpool = NULL;
- }
- // xstrfree -- release string buffer data
- xstr_p
- xstrfree(xstr_p xstr)
- {
- if (xstr != NULL) {
- #if XMEMCHK
- _xstrfree(xstr);
- #else
- xstr->xstr_prev = NULL;
- xstr->xstr_next = xstrpool;
- xstrpool = xstr;
- #endif
- xstr = NULL;
- }
- return xstr;
- }
- // _xstrfree -- release string buffer data
- void
- _xstrfree(xstr_p xstr)
- {
- char *lhs;
- if (xstr != NULL) {
- lhs = xstr->xstr_lhs;
- if (lhs != NULL)
- free(lhs);
- sysfree(xstr);
- }
- }
- // xstrshow -- show string contents
- void
- xstrshow(xstr_p xstr)
- {
- _dbgprt("xstrshow: TOKEN %s\n",_xstrshow(xstr));
- }
- // _xstrshow -- show string contents
- char *
- _xstrshow(xstr_p xstr)
- {
- char *bp;
- char *bf;
- bf = strtmp();
- bp = bf;
- bp += sprintf(bp,"[xstr=%p",xstr);
- if (xstr != NULL)
- bp += sprintf(bp," xstr_opt=%s xstr_lhs='%s'",
- strtgb(opt_tgb,xstr->xstr_opt),xstrcstr(xstr));
- bp += sprintf(bp,"]");
- return bf;
- }
- // xstrfree_dlv -- release string buffer data
- void
- xstrfree_dlv(dlk_p dlk)
- {
- xstrfree((xstr_p) dlk);
- }
- // xstrshow_dlv -- show data
- void
- xstrshow_dlv(dlk_p dlk,const char *reason)
- {
- xstrshow((xstr_p) dlk);
- }
- % shpipe.proto
- // /home/cae/preserve/ovrgen/shpipe/shpipe.proto -- prototypes
- // FILE: /home/cae/preserve/ovrbnc/shpipe/dlk.c
- // shpipe/dlk -- "smart" list "class" for C
- // dlhfree -- free list
- dlh_p
- dlhfree(dlh_p dlh);
- // _dlhfree -- clean list
- dlh_p
- _dlhfree(dlh_p dlh);
- // dlkpush -- append string to end of list
- dlk_p
- dlkpush(dlh_p dlh,dlk_p dlk);
- // dlhcut -- cut out entry and split list
- void
- dlhcut(dlh_p dlhlhs,dlh_p dlhrhs,dlk_p dlk);
- // dlkunlink -- remove item from list
- dlk_p
- dlkunlink(dlh_p dlh,dlk_p dlk);
- // dlhcnt -- calculate item count
- int
- dlhcnt(dlh_p dlh);
- // dlhshow -- output a list
- void
- dlhshow(dlh_p dlh,const char *reason);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/parse.c
- // shpipe/parse -- line parser
- //
- // NOTE: split on "&" first before ";"
- // parseline -- line buffer parser
- xcmd_p
- parseline(char *buf);
- // parsenew -- add char
- void
- parsenew(int chr,int type);
- // parsequo -- parse quoted string
- void
- parsequo(int quo);
- // tokmatch1 -- find a given token based on type and prefix value
- int
- tokmatch1(xstr_p xstr,int type,const char *src);
- // tokmatch2 -- find a given token based on type and exact value
- int
- tokmatch2(xstr_p xstr,int type,const char *src);
- // errprt -- show parsing error
- void
- errprt(xlst_p xlst,xcmd_p xcmd,xstr_p xstr,const char *fmt,...) __attribute__((__format__(__printf__,4,5)));
- // FILE: /home/cae/preserve/ovrbnc/shpipe/pipe.c
- // shpipe/pipe -- pipeline control
- // cmdpipefork -- attach pipe to given command in pipeline
- int
- cmdpipefork(xcmd_p xcmd,u32 popt,int pno,xcmd_p prev);
- // cmdpipeall -- set up piped job
- void
- cmdpipeall(xcmd_p xcmd);
- // cmdpipewait -- wait for pipeline to complete
- void
- cmdpipewait(xlst_p xlst);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/red.c
- // shpipe/red -- redirection and fork/exec control
- // cmdredall -- strip and setup redirections and fork/exec job
- void
- cmdredall(xcmd_p xcmd);
- // cmdredzone -- strip and setup redirections
- void
- cmdredzone(xcmd_p xcmd);
- // cmdredopen -- open redirection units in parent
- void
- cmdredopen(xcmd_p xcmd);
- // cmdredfork -- fork job
- void
- cmdredfork(xcmd_p xcmd);
- // cmdredclose -- close redirections and pipe units in parent
- void
- cmdredclose(xcmd_p xcmd,int errflg);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/shpipe.c
- // shpipe/shpipe -- shell with pipes
- // main -- main program
- int
- main(int argc,char **argv);
- // cmdsemi -- run a job
- void
- cmdsemi(xcmd_p xcmd);
- // cmdsplit -- split on token
- void
- cmdsplit(xlst_p xlst,xcmd_p xcmd,int type,char *sep,u32 opt);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/str.c
- // shpipe/str -- string functions
- // strtmp -- temporary persistent string buffer
- char *
- strtmp(void);
- // strtgb -- display option mask
- char *
- strtgb(tgb_p tgb,u32 opt);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/sysf.c
- // shpipe/sysf -- file descriptor leak detection
- // _closeme -- close a unit
- int
- _closeme(int fd,const char *file,int lno);
- // _xfdget -- get vector of currently open file descriptors
- void
- _xfdget(byte *vec);
- // _xfdchk -- get vector of currently open file descriptors
- void
- _xfdchk(byte *stdvec);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/sysm.c
- // shpipe/sysm -- memory leak detection
- // _syscalloc -- get new list
- void *
- _syscalloc(size_t cnt,size_t len,sysmagic_t magno,const char *file,int lno);
- // _sysfree -- free list
- void
- _sysfree(void *vp);
- // _sysmchk -- check memory
- void
- _sysmchk(void);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/xcmd.c
- // shpipe/xcmd -- "smart" list "class" for C
- // xcmdnew -- get new list
- xcmd_p
- xcmdnew(void);
- // xcmdfree -- free list
- xcmd_p
- xcmdfree(xcmd_p xcmd);
- // xcmdargv -- convert list to argv
- char **
- xcmdargv(xcmd_p xcmd,char **argv);
- // xcmdpush -- append string to end of list
- xstr_p
- xcmdpush(xcmd_p xcmd,xstr_p xstr);
- // xcmdfind1 -- find a given token based on type and prefix value
- xstr_p
- xcmdfind1(xcmd_p xcmd,int type,const char *src);
- // xcmdfind2 -- find a given token based on type and exact value
- xstr_p
- xcmdfind2(xcmd_p xcmd,int type,const char *src);
- // xcmdcut -- cut out entry and split list
- xcmd_p
- xcmdcut(xcmd_p xcmdrhs,xstr_p xstr);
- // xcmdunlink -- remove string from list
- xstr_p
- xcmdunlink(xcmd_p xcmd,xstr_p xstr);
- // xcmdcnt -- calculate string count
- int
- xcmdcnt(xcmd_p xcmd);
- // xcmdshow -- output a list
- void
- xcmdshow(xcmd_p xcmd,const char *reason);
- // xcmdfree_dlv -- release string buffer data
- void
- xcmdfree_dlv(dlk_p dlk);
- // xcmdshow_dlv -- show data
- void
- xcmdshow_dlv(dlk_p dlk,const char *reason);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/xlst.c
- // shpipe/xlst -- "smart" list "class" for C
- // xlstnew -- get new list
- xlst_p
- xlstnew(void);
- // xlstfree -- free list
- xlst_p
- xlstfree(xlst_p xlst);
- // xlstpush -- append string to end of list
- xcmd_p
- xlstpush(xlst_p xlst,xcmd_p xcmd);
- // xlstcut -- cut out entry and split list
- xlst_p
- xlstcut(xlst_p xlstrhs,xcmd_p xcmd);
- // xlstunlink -- remove string from list
- xcmd_p
- xlstunlink(xlst_p xlst,xcmd_p xcmd);
- // xlstcnt -- calculate string count
- int
- xlstcnt(xlst_p xlst);
- // xlstshow -- output a list
- void
- xlstshow(xlst_p xlst,const char *reason);
- // FILE: /home/cae/preserve/ovrbnc/shpipe/xstr.c
- // shpipe/xstr -- "smart" string "class" for C
- // xstragain -- reset string buffer
- void
- xstragain(xstr_p xstr);
- // xstrnew -- allocate string buffer
- xstr_p
- xstrnew(void);
- // xstrgrow -- grow string buffer
- void
- xstrgrow(xstr_p xstr,size_t needlen);
- // xstraddchar -- add character to string
- void
- xstraddchar(xstr_p xstr,int chr);
- // xstraddstr -- add string to string
- void
- xstraddstr(xstr_p xstr,const char *str);
- // xstrclean -- clean the pool
- void
- xstrclean(void);
- // xstrfree -- release string buffer data
- xstr_p
- xstrfree(xstr_p xstr);
- // _xstrfree -- release string buffer data
- void
- _xstrfree(xstr_p xstr);
- // xstrshow -- show string contents
- void
- xstrshow(xstr_p xstr);
- // _xstrshow -- show string contents
- char *
- _xstrshow(xstr_p xstr);
- // xstrfree_dlv -- release string buffer data
- void
- xstrfree_dlv(dlk_p dlk);
- // xstrshow_dlv -- show data
- void
- xstrshow_dlv(dlk_p dlk,const char *reason);
- % Makefile
- # shpipe/Makefile -- make file for shpipe
- #
- # SO: implementing input output redirection in a linux shell using c
- # SO: 35569673
- ifndef _shpipe_mk_
- _shpipe_mk_ = 1
- PGMTGT += shpipe
- PGMTGT += shredir
- OLIST-shpipe += dlk.o
- OLIST-shpipe += parse.o
- OLIST-shpipe += red.o
- OLIST-shpipe += pipe.o
- OLIST-shpipe += xcmd.o
- OLIST-shpipe += xstr.o
- OLIST-shpipe += xlst.o
- OLIST-shpipe += str.o
- OLIST-shpipe += sysm.o
- OLIST-shpipe += sysf.o
- DFLAGS += -I$(SDIR)
- DFLAGS += -I$(GENDIR)
- endif
- OVRPUB := 1
- # rules/rules.mk -- rules control
- #
- # options:
- # GDB -- enable debug symbols
- # 0 -- normal
- # 1 -- use -O0 and define _USE_GDB_=1
- #
- # CLANG -- use clang instead of gcc
- # 0 -- use gcc
- # 1 -- use clang
- #
- # CVERBOSE -- build verbosity
- # 0 -- normal
- # 1 -- add -v to cc and -Wl,--verbose to ld
- #
- # M32 -- cross-build to 32 bit mode
- # 0 -- native build
- # 1 -- build for i386
- #
- # BNC -- enable benchmarks
- # 0 -- normal mode
- # 1 -- enable benchmarks for function enter/exit pairs
- # 2 -- add min/max
- #
- # XCFLAGS -- extra command line CFLAGS
- # XDFLAGS -- extra command line DFLAGS
- #
- # DOT_I -- generate preprocessor output
- # DOT_S -- generate assembler output
- #
- # GLIB -- added options for glib
- #
- # symbols:
- # DFLAGS -- -D options
- # CFLAGS -- compiler options
- #
- # PREP -- targets to execute before ALL
- # ALL -- things to build (automatically uses LIBNAME/PGMTGT)
- #
- # LIBNAME -- library name to build (e.g. foo.a) -- can be multiple
- # OLIB -- list of .o files to build LIBNAME
- # OLIB-<libname> -- list of .o files to build <libname>
- #
- # PGMTGT -- program to build (e.g. fludger) -- can be multiple
- # OLIST -- list of .o files to build PGMTGT
- # OLIST-<pgmname> -- list of .o files to build <pgmname>
- #
- # CLEAN -- things to clean (automatically uses a bunch of stuff)
- #
- # NOPROTO -- do not generate prototypes
- # FINLINE -- allow gcc to inline functions automatically
- # WNOERROR -- inhibit -Werror
- # WEXTRA -- add -Wextra
- ifdef OVRPUB
- ifndef SDIR
- SDIR := $(shell pwd)
- STAIL := $(notdir $(SDIR))
- endif
- ifndef GENTOP
- GENTOP := $(dir $(SDIR))
- endif
- ifndef GENDIR
- GENDIR := $(GENTOP)/$(STAIL)
- endif
- ifndef ODIR
- ODIR := $(GENDIR)
- endif
- NOPROTO := 1
- endif
- # disable prototype generation
- ifdef NOPROTO
- PROTOLST := true
- PROTOGEN := @true
- else
- PROTOLST := qproto
- PROTOGEN := @qproto
- PROTOALL := proto
- endif
- ifndef SDIR
- $(error rules: SDIR not defined)
- endif
- ifndef ODIR
- $(error rules: ODIR not defined)
- endif
- ifndef GENDIR
- $(error rules: GENDIR not defined)
- endif
- ifndef GENTOP
- $(error rules: GENTOP not defined)
- endif
- ifndef _rules_mk_
- _rules_mk_ = 1
- ALL += $(LIBNAME) $(PGMTGT)
- CLEAN += $(LIBNAME) $(PGMTGT)
- ifndef NOPROTO
- CLEAN += *.proto
- endif
- CLEAN += *.a
- CLEAN += *.o
- CLEAN += *.i
- CLEAN += *.dis
- CLEAN += *.TMP
- QPROTO := $(shell $(PROTOLST) -i -l -O$(GENTOP) $(SDIR)/*.c $(CPROTO))
- HDEP += $(QPROTO)
- ###VPATH += $(GENDIR)
- ###VPATH += $(SDIR)
- ifdef INCLUDE_MK
- -include $(INCLUDE_MK)
- endif
- ifdef M32
- CFLAGS += -m32
- endif
- ifdef CVERBOSE
- CFLAGS += -v
- endif
- ifdef GSYM
- CFLAGS += -gdwarf-2
- endif
- ifdef GDB
- CFLAGS += -gdwarf-2
- DFLAGS += -D_USE_GDB_
- else
- CFLAGS += -O2
- endif
- ifdef DEBUG
- DFLAGS += -DDEBUG=$(DEBUG)
- endif
- ifndef ZPRT
- DFLAGS += -D_USE_ZPRT_=0
- endif
- ifdef BNC
- DFLAGS += -D_USE_BNC_=$(BNC)
- endif
- ifdef GLIB
- _GLIB = glib-2.0
- DFLAGS += $(shell pkg-config --cflags $(_GLIB))
- STDLIB += $(shell pkg-config --libs $(_GLIB))
- endif
- ifdef CLANG
- CC := clang
- CXX := clang++
- else
- ifdef CPLUS
- ifeq ($(STDLIB),)
- STDLIB += -lstdc++
- endif
- endif
- endif
- ifdef MPI
- export PATH := /usr/lib64/openmpi/bin:$(PATH)
- CC := mpicc
- CXX := mpicxx
- endif
- DFLAGS += -I$(GENTOP)
- DFLAGS += -I$(OVRTOP)
- DFLAGS += -I$(OVRBNC)
- CFLAGS += -Wall
- ifndef WNOERROR
- CFLAGS += -Werror
- endif
- ifdef WEXTRA
- CFLAGS += -Wextra
- endif
- CFLAGS += -Wno-unknown-pragmas
- CFLAGS += -Wempty-body
- CFLAGS += -fno-diagnostics-color
- ifdef DOT_I
- NOLDC := @true
- COPTS += -E -P
- O := i
- endif
- ifdef DOT_S
- NOLDC := @true
- COPTS += -S
- O := s
- endif
- ifndef COPTS
- COPTS += -c
- O := o
- endif
- ifndef FINLINE
- # NOTE: we now need this to prevent inlining (enabled at -O2)
- ifndef CLANG
- CFLAGS += -fno-inline-small-functions
- endif
- # NOTE: we now need this to prevent inlining (enabled at -O3)
- CFLAGS += -fno-inline-functions
- endif
- ifndef LDC
- ifdef CPLUS
- LDC = $(CXX)
- else
- LDC = $(CC)
- endif
- endif
- # FIXME/CAE -- gold wiki page says use -Wl but it seems to have no effect
- ifndef CLANG
- ###LDC += -Wl,-fuse-ld=ld.blah
- endif
- ifdef CVERBOSE
- LDC += -Wl,-verbose=2
- endif
- CFLAGS += $(XCFLAGS)
- DFLAGS += $(XDFLAGS)
- CFLAGS += $(DFLAGS)
- endif
- all: $(PREP) $(PROTOALL) $(ALL)
- # C
- %.o: %.c $(HDEP)
- $(CC) $(CFLAGS) $(COPTS) -o $*.$(O) $<
- %.i: %.c
- cpp $(DFLAGS) -P $*.c > $*.i
- %.s: %.c
- $(CC) $(CFLAGS) -S -o $*.s $<
- # C++
- %.o: %.cpp $(HDEP)
- $(CXX) $(CFLAGS) $(COPTS) -o $*.$(O) $<
- %.i: %.cpp
- cpp $(DFLAGS) -P $*.cpp > $*.i
- %.s: %.cpp
- $(CXX) $(CFLAGS) -S -o $*.s $<
- # asm
- %.o: %.s $(HDEP)
- $(AS) $(AFLAGS) -o $*.$(O) $<
- %.o: %.S $(HDEP)
- $(CC) $(CFLAGS) $(COPTS) -o $*.$(O) $<
- .SECONDEXPANSION:
- # build a library (type (2) build)
- $(LIBNAME):: $(OLIB) $$(OLIB-$$@)
- $(NOLDC) ar rv $@ $^
- # build programs
- $(PGMTGT):: [email protected] $(OLIST) $$(OLIST-$$@) $(LIBLIST)
- $(NOLDC) $(LDC) $(CFLAGS) -o $@ $^ $(STDLIB)
- .PHONY: proto
- proto::
- $(PROTOGEN) -i -v -O$(GENTOP) $(SDIR)/*.c $(CPROTO)
- .PHONY: clean
- clean::
- rm -f $(CLEAN)
- .PHONY: help
- help::
- egrep '^#' Makefile
Advertisement
Add Comment
Please, Sign In to add comment