Main Page | Class List | Directories | File List | Class Members | File Members

filefuncs.c

Go to the documentation of this file.
00001 /*
00002  * filefuncs.c - Builtin functions that provide initial minimal iterface
00003  *               to the file system.
00004  *
00005  * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998
00006  */
00007 
00008 /*
00009  * Copyright (C) 2001 the Free Software Foundation, Inc.
00010  * 
00011  * This file is part of GAWK, the GNU implementation of the
00012  * AWK Programming Language.
00013  * 
00014  * GAWK is free software; you can redistribute it and/or modify
00015  * it under the terms of the GNU General Public License as published by
00016  * the Free Software Foundation; either version 2 of the License, or
00017  * (at your option) any later version.
00018  * 
00019  * GAWK is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  * 
00024  * You should have received a copy of the GNU General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00027  */
00028 
00029 #include "awk.h"
00030 
00031 #include <sys/sysmacros.h>
00032 
00033 /*  do_chdir --- provide dynamically loaded chdir() builtin for gawk */
00034 
00035 static NODE *
00036 do_chdir(tree)
00037 NODE *tree;
00038 {
00039         NODE *newdir;
00040         int ret = -1;
00041 
00042         if  (do_lint && tree->param_cnt > 1)
00043                 lintwarn("chdir: called with too many arguments");
00044 
00045         newdir = get_argument(tree, 0);
00046         if (newdir != NULL) {
00047                 (void) force_string(newdir);
00048                 ret = chdir(newdir->stptr);
00049                 if (ret < 0)
00050                         update_ERRNO();
00051 
00052                 free_temp(newdir);
00053         } else if (do_lint)
00054                 lintwarn("chdir: called with no arguments");
00055 
00056 
00057         /* Set the return value */
00058         set_value(tmp_number((AWKNUM) ret));
00059 
00060         /* Just to make the interpreter happy */
00061         return tmp_number((AWKNUM) 0);
00062 }
00063 
00064 /* format_mode --- turn a stat mode field into something readable */
00065 
00066 static char *
00067 format_mode(fmode)
00068 unsigned long fmode;
00069 {
00070         static char outbuf[12];
00071         int i;
00072 
00073         strcpy(outbuf, "----------");
00074         /* first, get the file type */
00075         i = 0;
00076         switch (fmode & S_IFMT) {
00077 #ifdef S_IFSOCK
00078         case S_IFSOCK:
00079                 outbuf[i] = 's';
00080                 break;
00081 #endif
00082 #ifdef S_IFLNK
00083         case S_IFLNK:
00084                 outbuf[i] = 'l';
00085                 break;
00086 #endif
00087         case S_IFREG:
00088                 outbuf[i] = '-';        /* redundant */
00089                 break;
00090         case S_IFBLK:
00091                 outbuf[i] = 'b';
00092                 break;
00093         case S_IFDIR:
00094                 outbuf[i] = 'd';
00095                 break;
00096 #ifdef S_IFDOOR /* Solaris weirdness */
00097         case S_IFDOOR:
00098                 outbuf[i] = 'D';
00099                 break;
00100 #endif /* S_IFDOOR */
00101         case S_IFCHR:
00102                 outbuf[i] = 'c';
00103                 break;
00104 #ifdef S_IFIFO
00105         case S_IFIFO:
00106                 outbuf[i] = 'p';
00107                 break;
00108 #endif
00109         }
00110 
00111         i++;
00112         if ((fmode & S_IRUSR) != 0)
00113                 outbuf[i] = 'r';
00114         i++;
00115         if ((fmode & S_IWUSR) != 0)
00116                 outbuf[i] = 'w';
00117         i++;
00118         if ((fmode & S_IXUSR) != 0)
00119                 outbuf[i] = 'x';
00120         i++;
00121 
00122         if ((fmode & S_IRGRP) != 0)
00123                 outbuf[i] = 'r';
00124         i++;
00125         if ((fmode & S_IWGRP) != 0)
00126                 outbuf[i] = 'w';
00127         i++;
00128         if ((fmode & S_IXGRP) != 0)
00129                 outbuf[i] = 'x';
00130         i++;
00131 
00132         if ((fmode & S_IROTH) != 0)
00133                 outbuf[i] = 'r';
00134         i++;
00135         if ((fmode & S_IWOTH) != 0)
00136                 outbuf[i] = 'w';
00137         i++;
00138         if ((fmode & S_IXOTH) != 0)
00139                 outbuf[i] = 'x';
00140         i++;
00141 
00142         outbuf[i] = '\0';
00143 
00144         if ((fmode & S_ISUID) != 0) {
00145                 if (outbuf[3] == 'x')
00146                         outbuf[3] = 's';
00147                 else
00148                         outbuf[3] = 'S';
00149         }
00150 
00151         /* setgid without execute == locking */
00152         if ((fmode & S_ISGID) != 0) {
00153                 if (outbuf[6] == 'x')
00154                         outbuf[6] = 's';
00155                 else
00156                         outbuf[6] = 'l';
00157         }
00158 
00159         if ((fmode & S_ISVTX) != 0) {
00160                 if (outbuf[9] == 'x')
00161                         outbuf[9] = 't';
00162                 else
00163                         outbuf[9] = 'T';
00164         }
00165 
00166         return outbuf;
00167 }
00168 
00169 /* do_stat --- provide a stat() function for gawk */
00170 
00171 static NODE *
00172 do_stat(tree)
00173 NODE *tree;
00174 {
00175         NODE *file, *array;
00176         struct stat sbuf;
00177         int ret;
00178         NODE **aptr;
00179         char *pmode;    /* printable mode */
00180         char *type = "unknown";
00181 
00182         /* check arg count */
00183         if (tree->param_cnt != 2)
00184                 fatal(
00185         "stat: called with incorrect number of arguments (%d), should be 2",
00186                         tree->param_cnt);
00187 
00188         /* directory is first arg, array to hold results is second */
00189         file = get_argument(tree, 0);
00190         array = get_argument(tree, 1);
00191 
00192         array = get_array(array);
00193 
00194         /* empty out the array */
00195         assoc_clear(array);
00196 
00197         /* lstat the file, if error, set ERRNO and return */
00198         (void) force_string(file);
00199         ret = lstat(file->stptr, & sbuf);
00200         if (ret < 0) {
00201                 update_ERRNO();
00202 
00203                 set_value(tmp_number((AWKNUM) ret));
00204 
00205                 free_temp(file);
00206                 return tmp_number((AWKNUM) 0);
00207         }
00208 
00209         /* fill in the array */
00210         aptr = assoc_lookup(array, tmp_string("name", 4), FALSE);
00211         *aptr = dupnode(file);
00212 
00213         aptr = assoc_lookup(array, tmp_string("dev", 3), FALSE);
00214         *aptr = make_number((AWKNUM) sbuf.st_dev);
00215 
00216         aptr = assoc_lookup(array, tmp_string("ino", 3), FALSE);
00217         *aptr = make_number((AWKNUM) sbuf.st_ino);
00218 
00219         aptr = assoc_lookup(array, tmp_string("mode", 4), FALSE);
00220         *aptr = make_number((AWKNUM) sbuf.st_mode);
00221 
00222         aptr = assoc_lookup(array, tmp_string("nlink", 5), FALSE);
00223         *aptr = make_number((AWKNUM) sbuf.st_nlink);
00224 
00225         aptr = assoc_lookup(array, tmp_string("uid", 3), FALSE);
00226         *aptr = make_number((AWKNUM) sbuf.st_uid);
00227 
00228         aptr = assoc_lookup(array, tmp_string("gid", 3), FALSE);
00229         *aptr = make_number((AWKNUM) sbuf.st_gid);
00230 
00231         aptr = assoc_lookup(array, tmp_string("size", 4), FALSE);
00232         *aptr = make_number((AWKNUM) sbuf.st_size);
00233 
00234         aptr = assoc_lookup(array, tmp_string("blocks", 6), FALSE);
00235         *aptr = make_number((AWKNUM) sbuf.st_blocks);
00236 
00237         aptr = assoc_lookup(array, tmp_string("atime", 5), FALSE);
00238         *aptr = make_number((AWKNUM) sbuf.st_atime);
00239 
00240         aptr = assoc_lookup(array, tmp_string("mtime", 5), FALSE);
00241         *aptr = make_number((AWKNUM) sbuf.st_mtime);
00242 
00243         aptr = assoc_lookup(array, tmp_string("ctime", 5), FALSE);
00244         *aptr = make_number((AWKNUM) sbuf.st_ctime);
00245 
00246         /* for block and character devices, add rdev, major and minor numbers */
00247         if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode)) {
00248                 aptr = assoc_lookup(array, tmp_string("rdev", 4), FALSE);
00249                 *aptr = make_number((AWKNUM) sbuf.st_rdev);
00250 
00251                 aptr = assoc_lookup(array, tmp_string("major", 5), FALSE);
00252                 *aptr = make_number((AWKNUM) major(sbuf.st_rdev));
00253 
00254                 aptr = assoc_lookup(array, tmp_string("minor", 5), FALSE);
00255                 *aptr = make_number((AWKNUM) minor(sbuf.st_rdev));
00256         }
00257 
00258 #ifdef HAVE_ST_BLKSIZE
00259         aptr = assoc_lookup(array, tmp_string("blksize", 7), FALSE);
00260         *aptr = make_number((AWKNUM) sbuf.st_blksize);
00261 #endif /* HAVE_ST_BLKSIZE */
00262 
00263         aptr = assoc_lookup(array, tmp_string("pmode", 5), FALSE);
00264         pmode = format_mode(sbuf.st_mode);
00265         *aptr = make_string(pmode, strlen(pmode));
00266 
00267         /* for symbolic links, add a linkval field */
00268         if (S_ISLNK(sbuf.st_mode)) {
00269                 char buf[BUFSIZ*2];
00270                 int linksize;
00271 
00272                 linksize = readlink(file->stptr, buf, sizeof buf);
00273                 /* should make this smarter */
00274                 if (linksize == sizeof(buf))
00275                         fatal("size of symbolic link too big");
00276                 buf[linksize] = '\0';
00277 
00278                 aptr = assoc_lookup(array, tmp_string("linkval", 7), FALSE);
00279                 *aptr = make_string(buf, linksize);
00280         }
00281 
00282         /* add a type field */
00283         switch (sbuf.st_mode & S_IFMT) {
00284 #ifdef S_IFSOCK
00285         case S_IFSOCK:
00286                 type = "socket";
00287                 break;
00288 #endif
00289 #ifdef S_IFLNK
00290         case S_IFLNK:
00291                 type = "symlink";
00292                 break;
00293 #endif
00294         case S_IFREG:
00295                 type = "file";
00296                 break;
00297         case S_IFBLK:
00298                 type = "blockdev";
00299                 break;
00300         case S_IFDIR:
00301                 type = "directory";
00302                 break;
00303 #ifdef S_IFDOOR
00304         case S_IFDOOR:
00305                 type = "door";
00306                 break;
00307 #endif
00308         case S_IFCHR:
00309                 type = "chardev";
00310                 break;
00311 #ifdef S_IFIFO
00312         case S_IFIFO:
00313                 type = "fifo";
00314                 break;
00315 #endif
00316         }
00317 
00318         aptr = assoc_lookup(array, tmp_string("type", 4), FALSE);
00319         *aptr = make_string(type, strlen(type));
00320 
00321         free_temp(file);
00322 
00323         /* Set the return value */
00324         set_value(tmp_number((AWKNUM) ret));
00325 
00326         /* Just to make the interpreter happy */
00327         return tmp_number((AWKNUM) 0);
00328 }
00329 
00330 /* dlload --- load new builtins in this library */
00331 
00332 NODE *
00333 dlload(tree, dl)
00334 NODE *tree;
00335 void *dl;
00336 {
00337         make_builtin("chdir", do_chdir, 1);
00338         make_builtin("stat", do_stat, 2);
00339 
00340         return tmp_number((AWKNUM) 0);
00341 }

© sourcejam.com 2005-2008