Date: Mon, 23 Dec 2002 07:30:54 -0500 (EST) From: Alan Eldridge <alane@freebsd.org> To: FreeBSD-gnats-submit@freebsd.org Cc: demon@freebsd.org, ports@freebsd.org Message-ID: <200212231230.gBNCUsSL064381@wwweasel.geeksrus.net>
next in thread | raw e-mail | index | archive | help
>Submitter-Id: current-users >Originator: Alan Eldridge >Organization: Geeksrus.NET >Confidential: no >Synopsis: >Responsible: demon >Severity: serious >Priority: medium >Category: ports >Class: change-request >Release: FreeBSD 4.7-STABLE i386 >Environment: System: FreeBSD wwweasel.geeksrus.net 4.7-STABLE FreeBSD 4.7-STABLE #0: Fri Dec 20 06:38:48 EST 2002 root@wwweasel.geeksrus.net:/usr/obj/usr/src/sys/THRAK i386 >Description: Links, as great as it is, has no way to print. This patch hijacks the generic file open function, so anyplace you can enter a filename to save you can type "| command" and the data will go to the command instead. Printing is as easy as doing the "save formatted" command and giving a filename of "| lpr". This patch is non-invasive for the most part. It creates one new function (create_process(commandline)) in session.c, and adds an if statement to see if the save file begins with a "|": if it does we hijack it to create_process instead. I plan on submitting this to the author as well. However, it's a nice value-add for FreeBSD, and people are welcome to try it out on their own. The patch, which follows, is also available at: http://people.freebsd.org/~alane/patches/patch-links-save_to_pipe.txt >How-To-Repeat: >Fix: ==8<====8<====8<====8<====8<====8<====8<====8<====8<====8<== Index: files/patch-session.c =================================================================== RCS file: files/patch-session.c diff -N files/patch-session.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ files/patch-session.c 23 Dec 2002 12:07:48 -0000 @@ -0,0 +1,119 @@ +--- session.c.orig Sun Jun 9 15:49:24 2002 ++++ session.c Mon Dec 23 07:07:36 2002 +@@ -1,4 +1,4 @@ +-/* session.c ++/* session.c -*-mode: c; c-basic-offset: 8-*- + * (c) 2002 Mikulas Patocka + * This file is a part of the Links program, released under GPL. + */ +@@ -503,6 +503,95 @@ + } + } + ++int create_process(unsigned char *szfn) ++{ ++ int pid, rgfd[ 2 ]; ++ unsigned char *command = szfn; ++ ++ pipe(rgfd); ++ if ((pid = fork()) < 0) { ++ close(rgfd[ 0 ]); ++ close(rgfd[ 1 ]); ++ return -1; ++ } else if (pid > 0) { ++ /* parent: ++ 1. The write "handle" returned to the caller is ++ the canonical write end of the pipe pair. ++ 2. We close the "read" end since we are not using ++ it and we don't want fd leakage. ++ 3. The first thing the child is going to do is ++ fork and exit, so the process we want to run will ++ belong to init, not us. It's gross, but more ++ portable than becoming a session leader. So we wait. ++ */ ++ int status; ++ ++ wait(&status); ++ close(rgfd[ 0 ]); ++ return rgfd[ 1 ]; ++ } else { ++ /* child: ++ at this point, if something goes wrong, ++ there's really nothing we can do about it; ++ the parent will get a SIGPIPE when it ++ tries to write. ++ */ ++ int fdnull = open("/dev/null", O_WRONLY); ++ ++ /* ++ fork again, so we are re-parented to init ++ and avoid the whole SIGCHLD issue. if we ++ aren't the chile, we die. We use _exit so ++ we don't flush any output buffers. ++ */ ++ if ((pid = fork()) != 0) { ++ _exit(0); ++ } ++ ++ /* grandchild: ++ If we got here, we are in the grandchild process, ++ whose parent has died and been reaped. Our parent ++ should be init (the primordial process). ++ ++ Before we exec the command, we need to set up ++ stdin, stdout, and stderr. ++ 1. stdin gets a dup2 of the "read" end of the ++ pipe. ++ 2. stdout and stderr get copies of an fd opened ++ to "/dev/null". ++ */ ++ dup2(rgfd[ 0 ], 0); ++ dup2(fdnull, 1); ++ dup2(fdnull, 2); ++ ++ /* ++ Now we can close everything that is still ++ open, because we've dup'd what we needed. ++ */ ++ close(fdnull); ++ close(rgfd[ 0 ]); ++ close(rgfd[ 1 ]); ++ ++ /* ++ Let the shell handle the command. We use ++ a hard-coded /bin/sh to avoid someone setting ++ SHELL to an odd value and causing damage. ++ ++ Any damage that is done to the user should be ++ self-inflicted, not the result of a maliciously ++ set environment var. ++ */ ++ execlp("/bin/sh", "/bin/sh", "-c", command, 0); ++ ++ /* failure: ++ If we get here, there's not much to do but die. ++ We use _exit so we don't flush any output buffers. ++ */ ++ _exit(1); ++ } ++ /* Trust me, you can't get here. */ ++} ++ + int create_download_file(struct terminal *term, unsigned char *fi, int safe) + { + unsigned char *file = fi; +@@ -514,6 +603,14 @@ + #else + int sf = safe; + #endif ++ if (*fi == '|') { ++ /* ++ This will hook any command that saves ++ a file to disk and hijack it to write ++ to the input of a process. Cool, huh? ++ */ ++ return create_process(fi + 1); ++ } + wd = get_cwd(); + set_cwd(term->cwd); + if (file[0] == '~' && dir_sep(file[1])) { ==8<====8<====8<====8<====8<====8<====8<====8<====8<====8<== To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200212231230.gBNCUsSL064381>