home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / gawk-2.15.5-src.lha / gawk-2.15.5 / io.c < prev    next >
C/C++ Source or Header  |  1994-06-12  |  29KB  |  1,287 lines

  1. /*
  2.  * io.c --- routines for dealing with input and output and records
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #if !defined(VMS) && !defined(VMS_POSIX) && !defined(_MSC_VER)
  27. #include <sys/param.h>
  28. #endif
  29. #include "awk.h"
  30.  
  31. #ifndef O_RDONLY
  32. #include <fcntl.h>
  33. #endif
  34.  
  35. #if !defined(S_ISDIR) && defined(S_IFDIR)
  36. #define    S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
  37. #endif
  38.  
  39. #ifndef ENFILE
  40. #define ENFILE EMFILE
  41. #endif
  42.  
  43. #ifndef atarist
  44. #define INVALID_HANDLE (-1)
  45. #else
  46. #define INVALID_HANDLE  (__SMALLEST_VALID_HANDLE - 1)
  47. #endif
  48.  
  49. #if defined(MSDOS) || defined(OS2) || defined(atarist)
  50. #define PIPES_SIMULATED
  51. #endif
  52.  
  53. static IOBUF *nextfile P((int skipping));
  54. static int inrec P((IOBUF *iop));
  55. static int iop_close P((IOBUF *iop));
  56. struct redirect *redirect P((NODE *tree, int *errflg));
  57. static void close_one P((void));
  58. static int close_redir P((struct redirect *rp, int exitwarn));
  59. #ifndef PIPES_SIMULATED
  60. static int wait_any P((int interesting));
  61. #endif
  62. static IOBUF *gawk_popen P((char *cmd, struct redirect *rp));
  63. static IOBUF *iop_open P((const char *file, const char *how));
  64. static int gawk_pclose P((struct redirect *rp));
  65. static int do_pathopen P((const char *file));
  66. static int str2mode P((const char *mode));
  67. static void spec_setup P((IOBUF *iop, int len, int allocate));
  68. static int specfdopen P((IOBUF *iop, const char *name, const char *mode));
  69. static int pidopen P((IOBUF *iop, const char *name, const char *mode));
  70. static int useropen P((IOBUF *iop, const char *name, const char *mode));
  71.  
  72. extern FILE    *fdopen();
  73.  
  74. #if defined (MSDOS)
  75. #include "popen.h"
  76. #define popen(c,m)    os_popen(c,m)
  77. #define pclose(f)        os_pclose(f)
  78. #elif defined (OS2)    /* OS/2, but not family mode */
  79. #if defined (_MSC_VER)
  80. #define popen(c,m)   _popen(c,m)
  81. #define pclose(f)    _pclose(f)
  82. #endif
  83. #else
  84. extern FILE    *popen();
  85. #endif
  86.  
  87. static struct redirect *red_head = NULL;
  88.  
  89. extern int output_is_tty;
  90. extern NODE *ARGC_node;
  91. extern NODE *ARGV_node;
  92. extern NODE *ARGIND_node;
  93. extern NODE *ERRNO_node;
  94. extern NODE **fields_arr;
  95.  
  96. static jmp_buf filebuf;        /* for do_nextfile() */
  97.  
  98. /* do_nextfile --- implement gawk "next file" extension */
  99.  
  100. void
  101. do_nextfile()
  102. {
  103.     (void) nextfile(1);
  104.     longjmp(filebuf, 1);
  105. }
  106.  
  107. static IOBUF *
  108. nextfile(skipping)
  109. int skipping;
  110. {
  111.     static int i = 1;
  112.     static int files = 0;
  113.     NODE *arg;
  114.     static IOBUF *curfile = NULL;
  115.  
  116.     if (skipping) {
  117.         if (curfile != NULL)
  118.             iop_close(curfile);
  119.         curfile = NULL;
  120.         return NULL;
  121.     }
  122.     if (curfile != NULL) {
  123.         if (curfile->cnt == EOF) {
  124.             (void) iop_close(curfile);
  125.             curfile = NULL;
  126.         } else
  127.             return curfile;
  128.     }
  129.     for (; i < (int) (ARGC_node->lnode->numbr); i++) {
  130.         arg = *assoc_lookup(ARGV_node, tmp_number((AWKNUM) i));
  131.         if (arg->stptr[0] == '\0')
  132.             continue;
  133.         arg->stptr[arg->stlen] = '\0';
  134.         if (! do_unix) {
  135.             ARGIND_node->var_value->numbr = i;
  136.             ARGIND_node->var_value->flags = NUM|NUMBER;
  137.         }
  138.         if (!arg_assign(arg->stptr)) {
  139.             files++;
  140.             curfile = iop_open(arg->stptr, "r");
  141.             if (curfile == NULL)
  142.                 fatal("cannot open file `%s' for reading (%s)",
  143.                     arg->stptr, strerror(errno));
  144.                 /* NOTREACHED */
  145.             /* This is a kludge.  */
  146.             unref(FILENAME_node->var_value);
  147.             FILENAME_node->var_value = dupnode(arg);
  148.             FNR = 0;
  149.             i++;
  150.             break;
  151.         }
  152.     }
  153.     if (files == 0) {
  154.         files++;
  155.         /* no args. -- use stdin */
  156.         /* FNR is init'ed to 0 */
  157.         FILENAME_node->var_value = make_string("-", 1);
  158.         curfile = iop_alloc(fileno(stdin));
  159.     }
  160.     return curfile;
  161. }
  162.  
  163. void
  164. set_FNR()
  165. {
  166.     FNR = (long) FNR_node->var_value->numbr;
  167. }
  168.  
  169. void
  170. set_NR()
  171. {
  172.     NR = (long) NR_node->var_value->numbr;
  173. }
  174.  
  175. /*
  176.  * This reads in a record from the input file
  177.  */
  178. static int
  179. inrec(iop)
  180. IOBUF *iop;
  181. {
  182.     char *begin;
  183.     register int cnt;
  184.     int retval = 0;
  185.  
  186.     cnt = get_a_record(&begin, iop, *RS, NULL);
  187.     if (cnt == EOF) {
  188.         cnt = 0;
  189.         retval = 1;
  190.     } else {
  191.             NR += 1;
  192.             FNR += 1;
  193.     }
  194.     set_record(begin, cnt, 1);
  195.  
  196.     return retval;
  197. }
  198.  
  199. static int
  200. iop_close(iop)
  201. IOBUF *iop;
  202. {
  203.     int ret;
  204.  
  205.     if (iop == NULL)
  206.         return 0;
  207.     errno = 0;
  208.  
  209. #ifdef _CRAY
  210.     /* Work around bug in UNICOS popen */
  211.     if (iop->fd < 3)
  212.         ret = 0;
  213.     else
  214. #endif
  215.     /* save these for re-use; don't free the storage */
  216.     if ((iop->flag & IOP_IS_INTERNAL) != 0) {
  217.         iop->off = iop->buf;
  218.         iop->end = iop->buf + strlen(iop->buf);
  219.         iop->cnt = 0;
  220.         iop->secsiz = 0;
  221.         return 0;
  222.     }
  223.  
  224.     /* Don't close standard files or else crufty code elsewhere will lose */
  225.     if (iop->fd == fileno(stdin) ||
  226.         iop->fd == fileno(stdout) ||
  227.         iop->fd == fileno(stderr))
  228.         ret = 0;
  229.     else
  230.         ret = close(iop->fd);
  231.     if (ret == -1)
  232.         warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
  233.     if ((iop->flag & IOP_NO_FREE) == 0) {
  234.         /*
  235.          * be careful -- $0 may still reference the buffer even though
  236.          * an explicit close is being done; in the future, maybe we
  237.          * can do this a bit better
  238.          */
  239.         if (iop->buf) {
  240.             if ((fields_arr[0]->stptr >= iop->buf)
  241.                 && (fields_arr[0]->stptr < iop->end)) {
  242.                 NODE *t;
  243.     
  244.                 t = make_string(fields_arr[0]->stptr,
  245.                         fields_arr[0]->stlen);
  246.                 unref(fields_arr[0]);
  247.                 fields_arr [0] = t;
  248.                 reset_record ();
  249.             }
  250.               free(iop->buf);
  251.         }
  252.         free((char *)iop);
  253.     }
  254.     return ret == -1 ? 1 : 0;
  255. }
  256.  
  257. void
  258. do_input()
  259. {
  260.     IOBUF *iop;
  261.     extern int exiting;
  262.  
  263.     (void) setjmp(filebuf);
  264.  
  265.     while ((iop = nextfile(0)) != NULL) {
  266.         if (inrec(iop) == 0)
  267.             while (interpret(expression_value) && inrec(iop) == 0)
  268.                 continue;
  269.         /* recover any space from C based alloca */
  270.         (void) alloca(0);
  271.  
  272.         if (exiting)
  273.             break;
  274.     }
  275. }
  276.  
  277. /* Redirection for printf and print commands */
  278. struct redirect *
  279. redirect(tree, errflg)
  280. NODE *tree;
  281. int *errflg;
  282. {
  283.     register NODE *tmp;
  284.     register struct redirect *rp;
  285.     register char *str;
  286.     int tflag = 0;
  287.     int outflag = 0;
  288.     const char *direction = "to";
  289.     const char *mode;
  290.     int fd;
  291.     const char *what = NULL;
  292.  
  293.     switch (tree->type) {
  294.     case Node_redirect_append:
  295.         tflag = RED_APPEND;
  296.         /* FALL THROUGH */
  297.     case Node_redirect_output:
  298.         outflag = (RED_FILE|RED_WRITE);
  299.         tflag |= outflag;
  300.         if (tree->type == Node_redirect_output)
  301.             what = ">";
  302.         else
  303.             what = ">>";
  304.         break;
  305.     case Node_redirect_pipe:
  306.         tflag = (RED_PIPE|RED_WRITE);
  307.         what = "|";
  308.         break;
  309.     case Node_redirect_pipein:
  310.         tflag = (RED_PIPE|RED_READ);
  311.         what = "|";
  312.         break;
  313.     case Node_redirect_input:
  314.         tflag = (RED_FILE|RED_READ);
  315.         what = "<";
  316.         break;
  317.     default:
  318.         fatal ("invalid tree type %d in redirect()", tree->type);
  319.         break;
  320.     }
  321.     tmp = tree_eval(tree->subnode);
  322.     if (do_lint && ! (tmp->flags & STR))
  323.         warning("expression in `%s' redirection only has numeric value",
  324.             what);
  325.     tmp = force_string(tmp);
  326.     str = tmp->stptr;
  327.     if (str == NULL || *str == '\0')
  328.         fatal("expression for `%s' redirection has null string value",
  329.             what);
  330.     if (do_lint
  331.         && (STREQN(str, "0", tmp->stlen) || STREQN(str, "1", tmp->stlen)))
  332.         warning("filename `%s' for `%s' redirection may be result of logical expression", str, what);
  333.     for (rp = red_head; rp != NULL; rp = rp->next)
  334.         if (strlen(rp->value) == tmp->stlen
  335.             && STREQN(rp->value, str, tmp->stlen)
  336.             && ((rp->flag & ~(RED_NOBUF|RED_EOF)) == tflag
  337.             || (outflag
  338.                 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
  339.             break;
  340.     if (rp == NULL) {
  341.         emalloc(rp, struct redirect *, sizeof(struct redirect),
  342.             "redirect");
  343.         emalloc(str, char *, tmp->stlen+1, "redirect");
  344.         memcpy(str, tmp->stptr, tmp->stlen);
  345.         str[tmp->stlen] = '\0';
  346.         rp->value = str;
  347.         rp->flag = tflag;
  348.         rp->fp = NULL;
  349.         rp->iop = NULL;
  350.         rp-