xref: /plan9/sys/src/ape/cmd/pax/ttyio.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 /* $Source: /u/mark/src/pax/RCS/ttyio.c,v $
2  *
3  * $Revision: 1.2 $
4  *
5  * ttyio.c - Terminal/Console I/O functions for all archive interfaces
6  *
7  * DESCRIPTION
8  *
9  *	These routines provide a consistent, general purpose interface to
10  *	the user via the users terminal, if it is available to the
11  *	process.
12  *
13  * AUTHOR
14  *
15  *     Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
16  *
17  * Sponsored by The USENIX Association for public distribution.
18  *
19  * Copyright (c) 1989 Mark H. Colburn.
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms are permitted
23  * provided that the above copyright notice is duplicated in all such
24  * forms and that any documentation, advertising materials, and other
25  * materials related to such distribution and use acknowledge that the
26  * software was developed * by Mark H. Colburn and sponsored by The
27  * USENIX Association.
28  *
29  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  * $Log:	ttyio.c,v $
34  * Revision 1.2  89/02/12  10:06:11  mark
35  * 1.2 release fixes
36  *
37  * Revision 1.1  88/12/23  18:02:39  mark
38  * Initial revision
39  *
40  */
41 
42 #ifndef lint
43 static char *ident = "$Id: ttyio.c,v 1.2 89/02/12 10:06:11 mark Exp $";
44 static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
45 #endif /* ! lint */
46 
47 
48 /* Headers */
49 
50 #include "pax.h"
51 
52 
53 /* open_tty - open the terminal for interactive queries
54  *
55  * DESCRIPTION
56  *
57  * 	Assumes that background processes ignore interrupts and that the
58  *	open() or the isatty() will fail for processes which are not
59  *	attached to terminals. Returns a file descriptor or -1 if
60  *	unsuccessful.
61  *
62  * RETURNS
63  *
64  *	Returns a file descriptor which can be used to read and write
65  *	directly to the user's terminal, or -1 on failure.
66  *
67  * ERRORS
68  *
69  *	If SIGINT cannot be ignored, or the open fails, or the newly opened
70  *	terminal device is not a tty, then open_tty will return a -1 to the
71  *	caller.
72  */
73 
74 #ifdef __STDC__
75 
open_tty(void)76 int open_tty(void)
77 
78 #else
79 
80 int open_tty()
81 
82 #endif
83 {
84     int             fd;		/* file descriptor for terminal */
85     SIG_T         (*intr)();	/* used to restore interupts if signal fails */
86 
87     if ((intr = signal(SIGINT, SIG_IGN)) == SIG_IGN) {
88 	return (-1);
89     }
90     signal(SIGINT, intr);
91     if ((fd = open(TTY, O_RDWR)) < 0) {
92 	return (-1);
93     }
94     if (isatty(fd)) {
95 	return (fd);
96     }
97     close(fd);
98     return (-1);
99 }
100 
101 
102 /* nextask - ask a question and get a response
103  *
104  * DESCRIPTION
105  *
106  *	Give the user a prompt and wait for their response.  The prompt,
107  *	located in "msg" is printed, then the user is allowed to type
108  *	a response to the message.  The first "limit" characters of the
109  *	user response is stored in "answer".
110  *
111  *	Nextask ignores spaces and tabs.
112  *
113  * PARAMETERS
114  *
115  *	char *msg	- Message to display for user
116  *	char *answer	- Pointer to user's response to question
117  *	int limit	- Limit of length for user's response
118  *
119  * RETURNS
120  *
121  *	Returns the number of characters in the user response to the
122  *	calling function.  If an EOF was encountered, a -1 is returned to
123  *	the calling function.  If an error occured which causes the read
124  *	to return with a value of -1, then the function will return a
125  *	non-zero return status to the calling process, and abort
126  *	execution.
127  */
128 
129 #ifdef __STDC__
130 
nextask(char * msg,char * answer,int limit)131 int nextask(char *msg, char *answer, int limit)
132 
133 #else
134 
135 int nextask(msg, answer, limit)
136 char           *msg;		/* message to display for user */
137 char           *answer;		/* pointer to user's response to question */
138 int             limit;		/* limit of length for user's response */
139 
140 #endif
141 {
142     int             idx;	/* index into answer for character input */
143     int             got;	/* number of characters read */
144     char            c;		/* character read */
145 
146     if (ttyf < 0) {
147 	fatal("/dev/tty Unavailable");
148     }
149     write(ttyf, msg, (uint) strlen(msg));
150     idx = 0;
151     while ((got = read(ttyf, &c, 1)) == 1) {
152 	if (c == '\n') {
153 	    break;
154 	} else if (c == ' ' || c == '\t') {
155 	    continue;
156 	} else if (idx < limit - 1) {
157 	    answer[idx++] = c;
158 	}
159     }
160     if (got == 0) {		/* got an EOF */
161         return(-1);
162     }
163     if (got < 0) {
164 	fatal(strerror());
165     }
166     answer[idx] = '\0';
167     return(0);
168 }
169 
170 
171 /* lineget - get a line from a given stream
172  *
173  * DESCRIPTION
174  *
175  *	Get a line of input for the stream named by "stream".  The data on
176  *	the stream is put into the buffer "buf".
177  *
178  * PARAMETERS
179  *
180  *	FILE *stream		- Stream to get input from
181  *	char *buf		- Buffer to put input into
182  *
183  * RETURNS
184  *
185  * 	Returns 0 if successful, -1 at EOF.
186  */
187 
188 #ifdef __STDC__
189 
lineget(FILE * stream,char * buf)190 int lineget(FILE *stream, char *buf)
191 
192 #else
193 
194 int lineget(stream, buf)
195 FILE           *stream;		/* stream to get input from */
196 char           *buf;		/* buffer to put input into */
197 
198 #endif
199 {
200     int             c;
201 
202     for (;;) {
203 	if ((c = getc(stream)) == EOF) {
204 	    return (-1);
205 	}
206 	if (c == '\n') {
207 	    break;
208 	}
209 	*buf++ = c;
210     }
211     *buf = '\0';
212     return (0);
213 }
214 
215 
216 /* next - Advance to the next archive volume.
217  *
218  * DESCRIPTION
219  *
220  *	Prompts the user to replace the backup medium with a new volume
221  *	when the old one is full.  There are some cases, such as when
222  *	archiving to a file on a hard disk, that the message can be a
223  *	little surprising.  Assumes that background processes ignore
224  *	interrupts and that the open() or the isatty() will fail for
225  *	processes which are not attached to terminals. Returns a file
226  *	descriptor or -1 if unsuccessful.
227  *
228  * PARAMETERS
229  *
230  *	int mode	- mode of archive (READ, WRITE, PASS)
231  */
232 
233 #ifdef __STDC__
234 
next(int mode)235 void next(int mode)
236 
237 #else
238 
239 void next(mode)
240 int             mode;		/* mode of archive (READ, WRITE, PASS) */
241 
242 #endif
243 {
244     char            msg[200];	/* buffer for message display */
245     char            answer[20];	/* buffer for user's answer */
246     int             ret;
247 
248     close_archive();
249 
250     sprintf(msg, "%s: Ready for volume %u\n%s: Type \"go\" when ready to proceed (or \"quit\" to abort): \07",
251 		   myname, arvolume + 1, myname);
252     for (;;) {
253 	ret = nextask(msg, answer, sizeof(answer));
254 	if (ret == -1 || strcmp(answer, "quit") == 0) {
255 	    fatal("Aborted");
256 	}
257 	if (strcmp(answer, "go") == 0 && open_archive(mode) == 0) {
258 	    break;
259 	}
260     }
261     warnarch("Continuing", (OFFSET) 0);
262 }
263