/* $Source: /u/mark/src/pax/RCS/ttyio.c,v $ * * $Revision: 1.2 $ * * ttyio.c - Terminal/Console I/O functions for all archive interfaces * * DESCRIPTION * * These routines provide a consistent, general purpose interface to * the user via the users terminal, if it is available to the * process. * * AUTHOR * * Mark H. Colburn, NAPS International (mark@jhereg.mn.org) * * Sponsored by The USENIX Association for public distribution. * * Copyright (c) 1989 Mark H. Colburn. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice is duplicated in all such * forms and that any documentation, advertising materials, and other * materials related to such distribution and use acknowledge that the * software was developed * by Mark H. Colburn and sponsored by The * USENIX Association. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * $Log: ttyio.c,v $ * Revision 1.2 89/02/12 10:06:11 mark * 1.2 release fixes * * Revision 1.1 88/12/23 18:02:39 mark * Initial revision * */ #ifndef lint static char *ident = "$Id: ttyio.c,v 1.2 89/02/12 10:06:11 mark Exp $"; static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n"; #endif /* ! lint */ /* Headers */ #include "pax.h" /* open_tty - open the terminal for interactive queries * * DESCRIPTION * * Assumes that background processes ignore interrupts and that the * open() or the isatty() will fail for processes which are not * attached to terminals. Returns a file descriptor or -1 if * unsuccessful. * * RETURNS * * Returns a file descriptor which can be used to read and write * directly to the user's terminal, or -1 on failure. * * ERRORS * * If SIGINT cannot be ignored, or the open fails, or the newly opened * terminal device is not a tty, then open_tty will return a -1 to the * caller. */ #ifdef __STDC__ int open_tty(void) #else int open_tty() #endif { int fd; /* file descriptor for terminal */ SIG_T (*intr)(); /* used to restore interupts if signal fails */ if ((intr = signal(SIGINT, SIG_IGN)) == SIG_IGN) { return (-1); } signal(SIGINT, intr); if ((fd = open(TTY, O_RDWR)) < 0) { return (-1); } if (isatty(fd)) { return (fd); } close(fd); return (-1); } /* nextask - ask a question and get a response * * DESCRIPTION * * Give the user a prompt and wait for their response. The prompt, * located in "msg" is printed, then the user is allowed to type * a response to the message. The first "limit" characters of the * user response is stored in "answer". * * Nextask ignores spaces and tabs. * * PARAMETERS * * char *msg - Message to display for user * char *answer - Pointer to user's response to question * int limit - Limit of length for user's response * * RETURNS * * Returns the number of characters in the user response to the * calling function. If an EOF was encountered, a -1 is returned to * the calling function. If an error occured which causes the read * to return with a value of -1, then the function will return a * non-zero return status to the calling process, and abort * execution. */ #ifdef __STDC__ int nextask(char *msg, char *answer, int limit) #else int nextask(msg, answer, limit) char *msg; /* message to display for user */ char *answer; /* pointer to user's response to question */ int limit; /* limit of length for user's response */ #endif { int idx; /* index into answer for character input */ int got; /* number of characters read */ char c; /* character read */ if (ttyf < 0) { fatal("/dev/tty Unavailable"); } write(ttyf, msg, (uint) strlen(msg)); idx = 0; while ((got = read(ttyf, &c, 1)) == 1) { if (c == '\n') { break; } else if (c == ' ' || c == '\t') { continue; } else if (idx < limit - 1) { answer[idx++] = c; } } if (got == 0) { /* got an EOF */ return(-1); } if (got < 0) { fatal(strerror()); } answer[idx] = '\0'; return(0); } /* lineget - get a line from a given stream * * DESCRIPTION * * Get a line of input for the stream named by "stream". The data on * the stream is put into the buffer "buf". * * PARAMETERS * * FILE *stream - Stream to get input from * char *buf - Buffer to put input into * * RETURNS * * Returns 0 if successful, -1 at EOF. */ #ifdef __STDC__ int lineget(FILE *stream, char *buf) #else int lineget(stream, buf) FILE *stream; /* stream to get input from */ char *buf; /* buffer to put input into */ #endif { int c; for (;;) { if ((c = getc(stream)) == EOF) { return (-1); } if (c == '\n') { break; } *buf++ = c; } *buf = '\0'; return (0); } /* next - Advance to the next archive volume. * * DESCRIPTION * * Prompts the user to replace the backup medium with a new volume * when the old one is full. There are some cases, such as when * archiving to a file on a hard disk, that the message can be a * little surprising. Assumes that background processes ignore * interrupts and that the open() or the isatty() will fail for * processes which are not attached to terminals. Returns a file * descriptor or -1 if unsuccessful. * * PARAMETERS * * int mode - mode of archive (READ, WRITE, PASS) */ #ifdef __STDC__ void next(int mode) #else void next(mode) int mode; /* mode of archive (READ, WRITE, PASS) */ #endif { char msg[200]; /* buffer for message display */ char answer[20]; /* buffer for user's answer */ int ret; close_archive(); sprintf(msg, "%s: Ready for volume %u\n%s: Type \"go\" when ready to proceed (or \"quit\" to abort): \07", myname, arvolume + 1, myname); for (;;) { ret = nextask(msg, answer, sizeof(answer)); if (ret == -1 || strcmp(answer, "quit") == 0) { fatal("Aborted"); } if (strcmp(answer, "go") == 0 && open_archive(mode) == 0) { break; } } warnarch("Continuing", (OFFSET) 0); }