From owner-freebsd-hackers Fri Sep 26 04:59:30 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id EAA00598 for hackers-outgoing; Fri, 26 Sep 1997 04:59:30 -0700 (PDT) Received: from usr09.primenet.com (tlambert@usr09.primenet.com [206.165.6.209]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id EAA00592 for ; Fri, 26 Sep 1997 04:59:27 -0700 (PDT) Received: (from tlambert@localhost) by usr09.primenet.com (8.8.5/8.8.5) id EAA20125; Fri, 26 Sep 1997 04:59:15 -0700 (MST) From: Terry Lambert Message-Id: <199709261159.EAA20125@usr09.primenet.com> Subject: Re: Timeout for sh(1) 'read' ?? To: mike@smith.net.au (Mike Smith) Date: Fri, 26 Sep 1997 11:59:14 +0000 (GMT) Cc: hackers@FreeBSD.ORG In-Reply-To: <199709260748.RAA00456@word.smith.net.au> from "Mike Smith" at Sep 26, 97 05:18:45 pm X-Mailer: ELM [version 2.4 PL23] Content-Type: text Sender: owner-freebsd-hackers@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk > Hiho folks, a question for the sh(1) studs amongst you : > > - I want to prompt for input using 'read', and have the read return in > some fashion after a timeout. > > I'd like to do this just using sh, and I'm not too fussed about how > hairy it is. Any ideas? > > (If sh has to be modified to achieve this, would it be a useful thing > to bring back?) Write a "timedread" program that returns "TIMEOUT" or "USERDATA xxxxx" and do "timedread | read x" and look at the front of x? 8-) 8-). Or you can do it the hard way... Do you have a "force" command? It makes things easier, but it's not an absolute requirement... A very ugly way to achieve this can be done with a command that can TIOCSTI input to yourself. Basically, you: 1) fork (command &) 2) start the read in the child process 3) ls -l the tty to check keyboard activity once a second 4) use an eval to keep a second counter. 5) When it hits the magic number of idle seconds, "force" a cr to the child process. 6) exit the original process and let the child finish it's job with the "default" input. There are several variations on this: o Do you need to keep the original process around instead of baton-relaying to one or more children? You may need to use multiple child processes so that you can use the "jobs" command and write the child PID of the first child to the first child so it can tell it to it's child (I don't know how else to get parent process ID's in sh; sorry). This will probably involve at least a sleep 2 in two processes. 8-(. o Do you want default input, or do you want to distinguish a timeout from anything a user can type? If the latter, then you need to communicate the failure to read to the child, probably using a temp file or a pipe that you've assigned descriptors on. o Do you want to quit counting when there is any activity, like the boot prompt does? You will need to modify the time comparison code accordingly, and exit the watchdog if you do. o Do you not have a "force"? You will need a third process; do the watchdog, and do the read in the third process. Use a pipe shared between both kids. If the watchdog fires, kill the child doing the read and write a "WATCHDOG\n" up the pipe. The original process should read the pipe for that, or if the read completes, kill the watchdog if it hasn't killed itself already (see above), and write the result of the read up, like "USERINPUT $x\n". Look for the "WATCHDOG" as input, and if not there, strip the "USERINPUT " off the read result. Ah, my misspent youth, writing complex installs in sh... Terry Lambert terry@lambert.org --- Any opinions in this posting are my own and not those of my present or previous employers.