diff options
Diffstat (limited to 'extension')
-rw-r--r-- | extension/dl.c | 96 | ||||
-rwxr-xr-x | extension/doit | 1 | ||||
-rw-r--r-- | extension/filefuncs.c | 339 | ||||
-rw-r--r-- | extension/foo.awk | 9 | ||||
-rw-r--r-- | extension/fork.c | 106 | ||||
-rwxr-xr-x | extension/steps | 9 | ||||
-rw-r--r-- | extension/testff.awk | 30 | ||||
-rw-r--r-- | extension/testfork.awk | 20 |
8 files changed, 610 insertions, 0 deletions
diff --git a/extension/dl.c b/extension/dl.c new file mode 100644 index 00000000..0f1e1c5c --- /dev/null +++ b/extension/dl.c @@ -0,0 +1,96 @@ +/* + * dl.c - Example of adding a new builtin function to gawk. + * + * Christos Zoulas, Thu Jun 29 17:40:41 EDT 1995 + * Arnold Robbins, update for 3.1, Wed Sep 13 09:38:56 2000 + */ + +/* + * Copyright (C) 1995 - 2001 the Free Software Foundation, Inc. + * + * This file is part of GAWK, the GNU implementation of the + * AWK Programming Language. + * + * GAWK is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GAWK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "awk.h" +#include <dlfcn.h> + +static void *sdl = NULL; + +static NODE * +zaxxon(tree) +NODE *tree; +{ + NODE *obj; + int i; + int comma = 0; + + /* + * Print the arguments + */ + printf("External linkage %s(", tree->param); + + for (i = 0; i < tree->param_cnt; i++) { + + obj = get_argument(tree, i); + + if (obj == NULL) + break; + + force_string(obj); + + printf(comma ? ", %s" : "%s", obj->stptr); + free_temp(obj); + comma = 1; + } + + printf(");\n"); + + /* + * Do something useful + */ + obj = get_argument(tree, 0); + + if (obj != NULL) { + force_string(obj); + if (strcmp(obj->stptr, "unload") == 0 && sdl) { + /* + * XXX: How to clean up the function? + * I would like the ability to remove a function... + */ + dlclose(sdl); + sdl = NULL; + } + free_temp(obj); + } + + /* Set the return value */ + set_value(tmp_number((AWKNUM) 3.14)); + + /* Just to make the interpreter happy */ + return tmp_number((AWKNUM) 0); +} + +NODE * +dlload(tree, dl) +NODE *tree; +void *dl; +{ + sdl = dl; + make_builtin("zaxxon", zaxxon, 4); + return tmp_number((AWKNUM) 0); +} diff --git a/extension/doit b/extension/doit new file mode 100755 index 00000000..29dff7d8 --- /dev/null +++ b/extension/doit @@ -0,0 +1 @@ +../gawk -f foo.awk diff --git a/extension/filefuncs.c b/extension/filefuncs.c new file mode 100644 index 00000000..12badb5b --- /dev/null +++ b/extension/filefuncs.c @@ -0,0 +1,339 @@ +/* + * filefuncs.c - Builtin functions that provide initial minimal iterface + * to the file system. + * + * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998 + */ + +/* + * Copyright (C) 2001 the Free Software Foundation, Inc. + * + * This file is part of GAWK, the GNU implementation of the + * AWK Programming Language. + * + * GAWK is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GAWK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "awk.h" + +#include <sys/sysmacros.h> + +/* do_chdir --- provide dynamically loaded chdir() builtin for gawk */ + +static NODE * +do_chdir(tree) +NODE *tree; +{ + NODE *newdir; + int ret = -1; + + if (do_lint && tree->param_cnt > 1) + lintwarn("chdir: called with too many arguments"); + + newdir = get_argument(tree, 0); + if (newdir != NULL) { + (void) force_string(newdir); + ret = chdir(newdir->stptr); + if (ret < 0) + update_ERRNO(); + + free_temp(newdir); + } else if (do_lint) + lintwarn("chdir: called with no arguments"); + + + /* Set the return value */ + set_value(tmp_number((AWKNUM) ret)); + + /* Just to make the interpreter happy */ + return tmp_number((AWKNUM) 0); +} + +/* format_mode --- turn a stat mode field into something readable */ + +static char * +format_mode(fmode) +unsigned long fmode; +{ + static char outbuf[12]; + int i; + + strcpy(outbuf, "----------"); + /* first, get the file type */ + i = 0; + switch (fmode & S_IFMT) { +#ifdef S_IFSOCK + case S_IFSOCK: + outbuf[i] = 's'; + break; +#endif +#ifdef S_IFLNK + case S_IFLNK: + outbuf[i] = 'l'; + break; +#endif + case S_IFREG: + outbuf[i] = '-'; /* redundant */ + break; + case S_IFBLK: + outbuf[i] = 'b'; + break; + case S_IFDIR: + outbuf[i] = 'd'; + break; +#ifdef S_IFDOOR /* Solaris weirdness */ + case S_IFDOOR: + outbuf[i] = 'D'; + break; +#endif /* S_IFDOOR */ + case S_IFCHR: + outbuf[i] = 'c'; + break; +#ifdef S_IFIFO + case S_IFIFO: + outbuf[i] = 'p'; + break; +#endif + } + + i++; + if ((fmode & S_IRUSR) != 0) + outbuf[i] = 'r'; + i++; + if ((fmode & S_IWUSR) != 0) + outbuf[i] = 'w'; + i++; + if ((fmode & S_IXUSR) != 0) + outbuf[i] = 'x'; + i++; + + if ((fmode & S_IRGRP) != 0) + outbuf[i] = 'r'; + i++; + if ((fmode & S_IWGRP) != 0) + outbuf[i] = 'w'; + i++; + if ((fmode & S_IXGRP) != 0) + outbuf[i] = 'x'; + i++; + + if ((fmode & S_IROTH) != 0) + outbuf[i] = 'r'; + i++; + if ((fmode & S_IWOTH) != 0) + outbuf[i] = 'w'; + i++; + if ((fmode & S_IXOTH) != 0) + outbuf[i] = 'x'; + i++; + + outbuf[i] = '\0'; + + if ((fmode & S_ISUID) != 0) { + if (outbuf[3] == 'x') + outbuf[3] = 's'; + else + outbuf[3] = 'S'; + } + + /* setgid without execute == locking */ + if ((fmode & S_ISGID) != 0) { + if (outbuf[6] == 'x') + outbuf[6] = 's'; + else + outbuf[6] = 'l'; + } + + if ((fmode & S_ISVTX) != 0) { + if (outbuf[9] == 'x') + outbuf[9] = 't'; + else + outbuf[9] = 'T'; + } + + return outbuf; +} + +/* do_stat --- provide a stat() function for gawk */ + +static NODE * +do_stat(tree) +NODE *tree; +{ + NODE *file, *array; + struct stat sbuf; + int ret; + NODE **aptr; + char *pmode; /* printable mode */ + char *type = "unknown"; + + /* check arg count */ + if (tree->param_cnt != 2) + fatal( + "stat: called with incorrect number of arguments (%d), should be 2", + tree->param_cnt); + + /* directory is first arg, array to hold results is second */ + file = get_argument(tree, 0); + array = get_argument(tree, 1); + + /* empty out the array */ + assoc_clear(array); + + /* lstat the file, if error, set ERRNO and return */ + (void) force_string(file); + ret = lstat(file->stptr, & sbuf); + if (ret < 0) { + update_ERRNO(); + + set_value(tmp_number((AWKNUM) ret)); + + free_temp(file); + return tmp_number((AWKNUM) 0); + } + + /* fill in the array */ + aptr = assoc_lookup(array, tmp_string("name", 4), FALSE); + *aptr = dupnode(file); + + aptr = assoc_lookup(array, tmp_string("dev", 3), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_dev); + + aptr = assoc_lookup(array, tmp_string("ino", 3), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_ino); + + aptr = assoc_lookup(array, tmp_string("mode", 4), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_mode); + + aptr = assoc_lookup(array, tmp_string("nlink", 5), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_nlink); + + aptr = assoc_lookup(array, tmp_string("uid", 3), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_uid); + + aptr = assoc_lookup(array, tmp_string("gid", 3), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_gid); + + aptr = assoc_lookup(array, tmp_string("size", 4), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_size); + + aptr = assoc_lookup(array, tmp_string("blocks", 6), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_blocks); + + aptr = assoc_lookup(array, tmp_string("atime", 5), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_atime); + + aptr = assoc_lookup(array, tmp_string("mtime", 5), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_mtime); + + aptr = assoc_lookup(array, tmp_string("ctime", 5), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_ctime); + + /* for block and character devices, add rdev, major and minor numbers */ + if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode)) { + aptr = assoc_lookup(array, tmp_string("rdev", 4), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_rdev); + + aptr = assoc_lookup(array, tmp_string("major", 5), FALSE); + *aptr = make_number((AWKNUM) major(sbuf.st_rdev)); + + aptr = assoc_lookup(array, tmp_string("minor", 5), FALSE); + *aptr = make_number((AWKNUM) minor(sbuf.st_rdev)); + } + +#ifdef HAVE_ST_BLKSIZE + aptr = assoc_lookup(array, tmp_string("blksize", 7), FALSE); + *aptr = make_number((AWKNUM) sbuf.st_blksize); +#endif /* HAVE_ST_BLKSIZE */ + + aptr = assoc_lookup(array, tmp_string("pmode", 5), FALSE); + pmode = format_mode(sbuf.st_mode); + *aptr = make_string(pmode, strlen(pmode)); + + /* for symbolic links, add a linkval field */ + if (S_ISLNK(sbuf.st_mode)) { + char buf[BUFSIZ*2]; + int linksize; + + linksize = readlink(file->stptr, buf, sizeof buf); + /* should make this smarter */ + if (linksize == sizeof(buf)) + fatal("size of symbolic link too big"); + buf[linksize] = '\0'; + + aptr = assoc_lookup(array, tmp_string("linkval", 7), FALSE); + *aptr = make_string(buf, linksize); + } + + /* add a type field */ + switch (sbuf.st_mode & S_IFMT) { +#ifdef S_IFSOCK + case S_IFSOCK: + type = "socket"; + break; +#endif +#ifdef S_IFLNK + case S_IFLNK: + type = "symlink"; + break; +#endif + case S_IFREG: + type = "file"; + break; + case S_IFBLK: + type = "blockdev"; + break; + case S_IFDIR: + type = "directory"; + break; +#ifdef S_IFDOOR + case S_IFDOOR: + type = "door"; + break; +#endif + case S_IFCHR: + type = "chardev"; + break; +#ifdef S_IFIFO + case S_IFIFO: + type = "fifo"; + break; +#endif + } + + aptr = assoc_lookup(array, tmp_string("type", 4), FALSE); + *aptr = make_string(type, strlen(type)); + + free_temp(file); + + /* Set the return value */ + set_value(tmp_number((AWKNUM) ret)); + + /* Just to make the interpreter happy */ + return tmp_number((AWKNUM) 0); +} + +/* dlload --- load new builtins in this library */ + +NODE * +dlload(tree, dl) +NODE *tree; +void *dl; +{ + make_builtin("chdir", do_chdir, 1); + make_builtin("stat", do_stat, 2); + + return tmp_number((AWKNUM) 0); +} diff --git a/extension/foo.awk b/extension/foo.awk new file mode 100644 index 00000000..00a89e5b --- /dev/null +++ b/extension/foo.awk @@ -0,0 +1,9 @@ +BEGIN { + extension("./dl.so","dlload") + zaxxon("hi there", "this is", "a test", "of argument passing") + zaxxon(1) + zaxxon(1,2) + z = zaxxon(1,2,3,4) + z = zaxxon(1,zaxxon(zaxxon("foo")),3,4) + print z +} diff --git a/extension/fork.c b/extension/fork.c new file mode 100644 index 00000000..038a1689 --- /dev/null +++ b/extension/fork.c @@ -0,0 +1,106 @@ +/* + * fork.c - Provide fork and waitpid functions for gawk. + */ + +/* + * Copyright (C) 2001 the Free Software Foundation, Inc. + * + * This file is part of GAWK, the GNU implementation of the + * AWK Programming Language. + * + * GAWK is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GAWK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "awk.h" +#include <sys/wait.h> + +/* do_fork --- provide dynamically loaded fork() builtin for gawk */ + +static NODE * +do_fork(tree) +NODE *tree; +{ + int ret = -1; + NODE **aptr; + + if (do_lint && tree->param_cnt > 0) + lintwarn("fork: called with too many arguments"); + + ret = fork(); + + if (ret < 0) + update_ERRNO(); + else if (ret == 0) { + /* update PROCINFO in the child */ + + aptr = assoc_lookup(PROCINFO_node, tmp_string("pid", 3), FALSE); + (*aptr)->numbr = (AWKNUM) getpid(); + + aptr = assoc_lookup(PROCINFO_node, tmp_string("ppid", 4), FALSE); + (*aptr)->numbr = (AWKNUM) getppid(); + } + + /* Set the return value */ + set_value(tmp_number((AWKNUM) ret)); + + /* Just to make the interpreter happy */ + return tmp_number((AWKNUM) 0); +} + + +/* do_waitpid --- provide dynamically loaded waitpid() builtin for gawk */ + +static NODE * +do_waitpid(tree) +NODE *tree; +{ + NODE *pidnode; + int ret = -1; + double pidval; + pid_t pid; + int options = 0; + + if (do_lint && tree->param_cnt > 1) + lintwarn("waitpid: called with too many arguments"); + + pidnode = get_argument(tree, 0); + if (pidnode != NULL) { + pidval = force_number(pidnode); + pid = (int) pidval; + options = WNOHANG|WUNTRACED; + ret = waitpid(pid, NULL, options); + if (ret < 0) + update_ERRNO(); + } else if (do_lint) + lintwarn("wait: called with no arguments"); + + /* Set the return value */ + set_value(tmp_number((AWKNUM) ret)); + + /* Just to make the interpreter happy */ + return tmp_number((AWKNUM) 0); +} + +/* dlload --- load new builtins in this library */ + +NODE * +dlload(tree, dl) +NODE *tree; +void *dl; +{ + make_builtin("fork", do_fork, 0); + make_builtin("waitpid", do_waitpid, 1); + return tmp_number((AWKNUM) 0); +} diff --git a/extension/steps b/extension/steps new file mode 100755 index 00000000..61a9e6eb --- /dev/null +++ b/extension/steps @@ -0,0 +1,9 @@ +# what to do under linux to make dl.so +# Tue Nov 24 15:04:14 EST 1998 + +gcc -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. dl.c +gcc -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. filefuncs.c +gcc -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. fork.c +ld -o dl.so -shared dl.o +ld -o filefuncs.so -shared filefuncs.o +ld -o fork.so -shared fork.o diff --git a/extension/testff.awk b/extension/testff.awk new file mode 100644 index 00000000..0a0a9b2f --- /dev/null +++ b/extension/testff.awk @@ -0,0 +1,30 @@ +BEGIN { + extension("./filefuncs.so", "dlload") + +# printf "before: " +# fflush() +# system("pwd") +# +# chdir("..") +# +# printf "after: " +# fflush() +# system("pwd") + + chdir(".") + + data[1] = 1 + print "Info for testff.awk" + ret = stat("testff.awk", data) + print "ret =", ret + for (i in data) + printf "data[\"%s\"] = %s\n", i, data[i] + print "testff.awk modified:", strftime("%m %d %y %H:%M:%S", data["mtime"]) + + print "\nInfo for JUNK" + ret = stat("JUNK", data) + print "ret =", ret + for (i in data) + printf "data[\"%s\"] = %s\n", i, data[i] + print "JUNK modified:", strftime("%m %d %y %H:%M:%S", data["mtime"]) +} diff --git a/extension/testfork.awk b/extension/testfork.awk new file mode 100644 index 00000000..ca00dca8 --- /dev/null +++ b/extension/testfork.awk @@ -0,0 +1,20 @@ +BEGIN { + extension("./fork.so", "dlload") + + printf "before fork, pid = %d, ppid = %d\n", PROCINFO["pid"], + PROCINFO["ppid"] + + fflush() + ret = fork() + if (ret < 0) + printf("ret = %d, ERRNO = %s\n", ret, ERRNO) + else if (ret == 0) + printf "child, pid = %d, ppid = %d\n", PROCINFO["pid"], + PROCINFO["ppid"] + else { + system("sleep 3") + printf "parent, ret = %d\n", ret + printf "parent, pid = %d, ppid = %d\n", PROCINFO["pid"], + PROCINFO["ppid"] + } +} |