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