/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.0 (the 'License'). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License." * * @APPLE_LICENSE_HEADER_END@ */ /* * Alert handling (allow user to abort local domain binding) * Copyright (C) 1989 by NeXT, Inc. * */ #include /* * Disabled for MacOS X for the momment, * There's no support for console alerts yet. */ #ifdef _OS_APPLE_ static int aborted = 0; static enum { ALERT_FRESH, ALERT_OPENED, ALERT_PRINTED, ALERT_CLOSED } alert_state = ALERT_CLOSED; void alert_enable(int enable) { if (enable) alert_state = ALERT_FRESH; else alert_state = ALERT_CLOSED; } int alert_aborted(void) { return aborted; } void alert_close(void) { if (alert_state != ALERT_PRINTED) return; alert_state = ALERT_CLOSED; } void alert_open(const char *language) { if (alert_state != ALERT_FRESH) return; alert_state = ALERT_PRINTED; } #else #include #include #include #include #include #include #ifdef _OS_NEXT_ #define BUNDLE_PATH "/usr/lib/NextStep/Resources" #define _PATH_CONSOLE "/dev/console" #else #define BUNDLE_PATH "/System/Library/CoreServices/Resources" #include #endif #ifndef _PATH_CONSOLE #include #endif #include "ni_globals.h" #include "system.h" #include #define KERNEL_PRIVATE #include #undef KERNEL_PRIVATE #define MAXLINE 4096 #define STRING_TABLE "NetInfo" static const char SEARCH_MESSAGE[] = "\\nStill searching for parent network administration (NetInfo) " "server.\\nPlease wait, or press 'c' to continue without network " "user accounts.\\n\\nSee your system administrator if you need help.\\n"; static const char MESSAGE[] = "\nStill searching for parent network administration (NetInfo) " "server.\nPlease wait, or press 'c' to continue without network " "user accounts.\n\nSee your system administrator if you need help.\n"; static int aborted = 0; static int console; static int console_flags; static struct sgttyb console_sg; static enum { ALERT_FRESH, ALERT_OPENED, ALERT_PRINTED, ALERT_CLOSED } alert_state = ALERT_CLOSED; /* * Enable (or disable) alerts */ void alert_enable(int enable) { if (enable) alert_state = ALERT_FRESH; else alert_state = ALERT_CLOSED; } /* * Did the user abort the alert? */ int alert_aborted(void) { return (aborted); } /* * Close an alert */ void alert_close(void) { if (alert_state != ALERT_PRINTED) return; alert_state = ALERT_CLOSED; /* Restore fd flags */ fcntl(console, F_SETFL, console_flags); /* Restore terminal parameters */ ioctl(console, TIOCSETP, &console_sg); /* Remove the window */ ioctl(console, KMIOCRESTORE, 0); close(console); } /* * We got a SIGIO. Handle it. */ static void handle_io(int ignored) { char buf[512]; char *cp; int nchars; while ((nchars = read(console, (char *)&buf, sizeof(buf))) > 0) { cp = buf; while (nchars--) { if ((*cp == 'c') || (*cp == 'C')) { system_log(LOG_DEBUG, "Binding aborted"); aborted = 1; alert_close(); return; } cp++; } } if (errno != EWOULDBLOCK) alert_close(); } /* * Open an alert */ void alert_open(const char *language) { struct sgttyb sg; FILE *fp; char filename[MAXPATHLEN + 1]; char buf[MAXLINE]; char outmsg[MAXLINE]; int i, j, len; if (alert_state != ALERT_FRESH) return; alert_state = ALERT_OPENED; /* Open up the console */ if ((console = open(_PATH_CONSOLE, (O_RDWR|O_ALERT), 0)) < 0) { system_log(LOG_ERR, "console open failed: %s", strerror(errno)); aborted = 1; return; } /* Flush any existing input */ ioctl(console, TIOCFLUSH, FREAD); /* Set it up to interrupt on input */ if ((console_flags = fcntl(console, F_GETFL, 0)) == -1) { system_log(LOG_ERR, "console F_GETFL fcntl failed: %s", strerror(errno)); aborted = 1; close(console); return; } if (fcntl(console, F_SETFL, (console_flags|FASYNC|FNDELAY)) == -1) { system_log(LOG_ERR, "console F_SETFL fcntl failed: %s", strerror(errno)); aborted = 1; close(console); return; } signal(SIGIO, handle_io); /* Put it in CBREAK mode */ if (ioctl(console, TIOCGETP, &sg) == -1) { system_log(LOG_ERR, "console TIOCGETP ioctl failed: %s", strerror(errno)); aborted = 1; close(console); return; } console_sg = sg; sg.sg_flags |= CBREAK; sg.sg_flags &= ~ECHO; if (ioctl(console, TIOCSETP, &sg) == -1) { system_log(LOG_ERR, "console TIOCSETP ioctl failed: %s", strerror(errno)); aborted = 1; close(console); return; } alert_state = ALERT_PRINTED; sprintf(filename, "%s/%s.lproj/%s.strings", BUNDLE_PATH, language, STRING_TABLE); len = strlen(MESSAGE); fp = fopen(filename, "r"); if (fp == NULL) { write(console, MESSAGE, len); return; } while (fgets(buf, MAXLINE, fp) != NULL) { if (!strncmp(buf+1, SEARCH_MESSAGE, len)) { for (i = strlen(buf); ((buf[i] != '\"') && (i > 0)); i--); if (i <= 0) break; buf[i] = '\0'; for (i = strlen(SEARCH_MESSAGE) + 2; ((buf[i] != '\0') && (buf[i] != '\"')); i++); if (buf[i] == '\0') break; i++; j = 0; for (; buf[i] != '\0'; i++) { if ((buf[i] == '\\') && (buf[i+1] == 'n')) { i++; outmsg[j++] = '\n'; } else outmsg[j++] = buf[i]; } if (j == 0) break; fclose(fp); outmsg[j] = '\0'; write(console, outmsg, j); return; } } fclose(fp); write(console, MESSAGE, len); } #endif NO_CONSOLE_SUPPORT