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