This is unix.c in view mode; [Download] [Up]
/* * Copyright (c) 1992, 1995 John E. Davis (davis@space.mit.edu) * All Rights Reserved. */ #include <config.h> #include <stdio.h> #include "sysdep.h" #ifdef HAS_SUBPROCESSES #include "jprocess.h" #endif #include <signal.h> /* sequent support thanks to Kenneth Lorber <keni@oasys.dt.navy.mil> */ /* SYSV (SYSV ISC R3.2 v3.0) provided by iain.lea@erlm.siemens.de */ #include <sys/time.h> #ifdef HAVE_TERMIOS_H # if !defined(HAVE_TCGETATTR) || !defined(HAVE_TCSETATTR) # undef HAVE_TERMIOS_H # endif #endif #ifdef HAVE_TERMIOS_H # include <termios.h> #endif #ifdef sun #ifndef PENDIN #include <sys/ioctl.h> #endif #else #include <sys/ioctl.h> #endif #ifdef __QNX__ # include <termios.h> # include <sys/select.h> #endif #ifdef SYSV # ifndef CRAY # include <sys/termio.h> # include <sys/stream.h> # include <sys/ptem.h> # include <sys/tty.h> # endif #endif #include <sys/types.h> #include <sys/time.h> /* Another hack for AInt uniX (AIX) */ #if defined (_AIX) && !defined (FD_SET) # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */ #endif #include <sys/stat.h> #include <errno.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif # include <sys/file.h> # ifdef SYSV # include <sys/fcntl.h> # endif #ifndef F_GETFL # include <fcntl.h> #endif #include "sig.h" #define TTY_DESC 2 static int Read_FD = TTY_DESC; static int Max_Fd = TTY_DESC; int Flow_Control; int Abort_Char = 7; /* scan code for G (control) */ #ifndef HAVE_TERMIOS_H struct ttystuff { struct tchars t; struct ltchars lt; struct sgttyb s; }; struct ttystuff OLDTTY; #else struct termios OLDTTY; #endif #ifdef TCGETS #define GET_TERMIOS(fd, x) ioctl(fd, TCGETS, x) #define SET_TERMIOS(fd, x) ioctl(fd, TCSETS, x) #else # ifndef HAVE_TERMIOS_H # define X(x,m) &(((struct ttystuff*)(x))->m) # define GET_TERMIOS(fd, x) \ if(ioctl(fd, TIOCGETC, X(x,t))<0 || \ ioctl(fd, TIOCGLTC, X(x,lt))<0 || \ ioctl(fd, TIOCGETP, X(x,s))<0)exit_error("Can't get terminal info", 0) # define SET_TERMIOS(fd, x) \ if(ioctl(fd, TIOCSETC, X(x,t))<0 || \ ioctl(fd, TIOCSLTC, X(x,lt))<0 || \ ioctl(fd, TIOCSETP, X(x,s))<0)exit_error("Can't set terminal info", 0) # else # define GET_TERMIOS(fd, x) tcgetattr(fd, x) # define SET_TERMIOS(fd, x) tcsetattr(fd, TCSAFLUSH, x) /* # define SET_TERMIOS(fd, x) tcsetattr(fd, TCSANOW, x) */ # endif #endif static int Baud_Rates[20] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 0, 0, 0, 0 }; #ifdef HAS_MOUSE static int JMouse_Fd = -1; #endif static int tty_inited = 0; #define NULL_VALUE 0 void init_tty (void) { #ifndef HAVE_TERMIOS_H struct ttystuff newtty; #else struct termios newtty; #endif if (Batch) return; tty_inited = 1; if (X_Init_Term_Hook != NULL) { Read_FD = (*X_Init_Term_Hook) (); Max_Fd = Read_FD; return; } tt_enable_cursor_keys(); GET_TERMIOS(Read_FD, &OLDTTY); GET_TERMIOS(Read_FD, &newtty); #ifndef HAVE_TERMIOS_H newtty.s.sg_flags &= ~(ECHO); newtty.s.sg_flags &= ~(CRMOD); /* if (Flow_Control == 0) newtty.s.sg_flags &= ~IXON; */ newtty.t.t_eofc = 1; newtty.t.t_intrc = Abort_Char; /* ^G */ newtty.t.t_quitc = 255; newtty.lt.t_suspc = 255; /* to ignore ^Z */ newtty.lt.t_dsuspc = 255; /* to ignore ^Y */ newtty.lt.t_lnextc = 255; newtty.s.sg_flags |= CBREAK; /* do I want cbreak or raw????? */ #else if (*tt_Baud_Rate == 0) { /* Note: if this generates an compiler error, simply remove the statement */ #ifdef HAVE_CFGETOSPEED *tt_Baud_Rate = cfgetospeed (&newtty); #endif *tt_Baud_Rate = (*tt_Baud_Rate > 0) && (*tt_Baud_Rate < 19) ? Baud_Rates[*tt_Baud_Rate] : -1; } newtty.c_iflag &= ~(ECHO | INLCR | ICRNL); #ifdef ISTRIP /* allow 8 bit chars to pass through */ /* newtty.c_iflag &= ~ISTRIP; */ #endif newtty.c_oflag &= ~OPOST; /* (ONLCR | OPOST); */ /* do not map newline to cr/newline on out */ if (Flow_Control == 0) newtty.c_iflag &= ~IXON; newtty.c_cc[VMIN] = 1; newtty.c_cc[VTIME] = 0; newtty.c_cc[VEOF] = 1; newtty.c_lflag = ISIG | NOFLSH; newtty.c_cc[VINTR] = Abort_Char; /* ^G */ newtty.c_cc[VQUIT] = NULL_VALUE; newtty.c_cc[VSUSP] = NULL_VALUE; /* to ignore ^Z */ #ifdef VDSUSP newtty.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */ #endif #ifdef VSWTCH newtty.c_cc[VSWTCH] = NULL_VALUE; /* to ignore who knows what */ #endif #endif /* NOT HAVE_TERMIOS_H */ SET_TERMIOS(Read_FD, &newtty); #ifdef HAS_MOUSE if ((X_Open_Mouse_Hook != NULL) && ((JMouse_Fd = (*X_Open_Mouse_Hook)()) >= 0)) { if (JMouse_Fd > Read_FD) Max_Fd = JMouse_Fd; } #endif } void reset_tty (void) { if (Batch) return; if (!tty_inited) return; if (X_Init_Term_Hook != NULL) { if (X_Reset_Term_Hook != NULL) (*X_Reset_Term_Hook) (); return; } SET_TERMIOS(Read_FD, &OLDTTY); /* This statement ensures init_tty will not try to change output_rate (when coming back from suspension) */ if (*tt_Baud_Rate == 0) *tt_Baud_Rate = -1; #ifdef HAS_MOUSE if (X_Close_Mouse_Hook != NULL) X_Close_Mouse_Hook (); JMouse_Fd = -1; #endif } unsigned char sys_getkey (void) { int n = 450; int count = 3; unsigned char c; #ifdef HAS_SUBPROCESSES int all = Num_Subprocesses; #else int all = 0; #endif if (SLKeyBoard_Quit) return((int) Abort_Char); /* sleep for 45 second and try again */ while (!SLKeyBoard_Quit && !sys_input_pending(&n, all)) { /* update status line incase user is displaying time */ if (SLKeyBoard_Quit) break; if (Display_Time || all) { JWindow->trashed = 1; update((Line *) NULL, 0, 1); } } if (SLKeyBoard_Quit) return(Abort_Char); if (X_Read_Hook != NULL) return (X_Read_Hook ()); /* Something may have stuffed it, e.g., mouse */ if (Input_Buffer_Len) return my_getkey (); #ifdef HAS_MOUSE if (JMouse_Hide_Mouse_Hook != NULL) (*JMouse_Hide_Mouse_Hook) (0); #endif again: while (count-- && (read(Read_FD, (char *) &c, 1) < 0) && !SLKeyBoard_Quit) sleep(1); if (count <= 0) { count = 3; if (errno == EINTR) goto again; exit_error ("getkey(): read failed", 0); } /* only way for keyboard quit to be non zero is if ^G recived and sigint processed */ if (SLKeyBoard_Quit) c = Abort_Char; SLKeyBoard_Quit = 0; return(c); } #ifndef FD_SET #define FD_SET(fd, tthis) *(tthis) |= 1 << fd #define FD_ZERO(tthis) *(tthis) = 0 #define FD_ISSET(fd, tthis) (*(tthis) & (1 << fd)) typedef int fd_set; #endif static fd_set Read_FD_Set; /* If all is zero, only check for mouse or keyboard input. If all is -1, * check for only subprocess input. Otherwise, check all input. */ static int sys_input_pending(int *tsecs, int all) { struct timeval wait; long usecs, secs; int ret, maxfd; #ifdef HAS_SUBPROCESSES int i; #endif if ((all >= 0) && (Input_Buffer_Len || Batch)) return(Input_Buffer_Len); top: secs = *tsecs / 10; usecs = (*tsecs % 10) * 100000; wait.tv_sec = secs; wait.tv_usec = usecs; if (all >= 0) { if (X_Input_Pending_Hook != NULL) { if ((*X_Input_Pending_Hook) ()) return 1; } FD_SET(Read_FD, &Read_FD_Set); #ifdef HAS_MOUSE if ((JMouse_Fd >= 0) && (JMouse_Event_Hook != NULL)) { FD_SET (JMouse_Fd, &Read_FD_Set); } #endif maxfd = Max_Fd; } else maxfd = -1; #ifdef HAS_SUBPROCESSES if (all) { i = 0; while (i < Num_Subprocesses) { FD_SET(Subprocess_Read_fds[i][0], &Read_FD_Set); i++; } if (Max_Subprocess_FD > maxfd) maxfd = Max_Subprocess_FD; } #endif ret = select(maxfd + 1, &Read_FD_Set, NULL, NULL, &wait); if (ret == 0) return 0; #ifdef EBADF if ((ret < 0) && (errno == EBADF)) { /* Oh Geez. We have an invalid file descriptor. Well, there are * several options. Here is what I am choosing: If we are selecting * on subprocesses and the bad descriptor appears to be the subprocess * then ignore select on suprocesses. Hopefully the subprocess child * handlers will fire and illiminate this situation. If it is the * mouse, then turn off the mouse. If it is the keyboard, then exit. */ FD_ZERO (&Read_FD_Set); if (all >= 0) { #ifdef HAS_MOUSE if ((JMouse_Fd >= 0) && (JMouse_Event_Hook != NULL)) { if ((-1 == fcntl (JMouse_Fd, F_GETFL, 0)) && (errno == EBADF)) { JMouse_Event_Hook = NULL; goto top; } } #endif if ((-1 == fcntl (Read_FD, F_GETFL, 0)) && (errno == EBADF)) { exit_error ("select: keyboard file descriptor is bad!!!", 1); } } if (all == -1) return 0; all = 0; goto top; } #endif if (all >= 0) { if ((X_Input_Pending_Hook != NULL) && (ret > 0) && (FD_ISSET(Read_FD, &Read_FD_Set))) { if ((*X_Input_Pending_Hook) ()) return 1; /* Nothing there so try to time out again --- too bad select does * not inform of of how far we got. */ FD_SET(Read_FD, &Read_FD_Set); (void) select(Read_FD + 1, &Read_FD_Set, NULL, NULL, &wait); /* try again, it could be more bogus Xpackets. Event driven systems * are not always the way to go. */ return (*X_Input_Pending_Hook) (); } if (ret < 0) return 0; if (FD_ISSET(Read_FD, &Read_FD_Set)) return ret; /* Nothing to read from the terminal so while we are waiting * for tty input, read from those that are available. TTY input * always gets preference. */ #ifdef HAS_MOUSE if ((JMouse_Event_Hook != NULL) && (JMouse_Fd >= 0) && (FD_ISSET (JMouse_Fd, &Read_FD_Set))) { if ((*JMouse_Event_Hook) () > 0) { return 1; } /* This is ugly. */ goto top; } #endif } /* all >= 0 */ if (ret <= 0) return 0; #ifdef HAS_SUBPROCESSES i = 0; while (i < Num_Subprocesses) { if (FD_ISSET(Subprocess_Read_fds[i][0], &Read_FD_Set)) read_process_input (i); i++; } #endif if (all < 0) return ret; return 0; /* no keyboard input */ } /* This is to get the size of the terminal */ int get_term_dimensions(int *cols, int *rows) { #ifdef TIOCGWINSZ struct winsize wind_struct; if (X_Get_Term_Size_Hook == NULL) { if ((ioctl(1,TIOCGWINSZ,&wind_struct) < 0) && (ioctl(2, TIOCGWINSZ, &wind_struct) < 0) && (ioctl(0, TIOCGWINSZ, &wind_struct) < 0)) { *rows = *cols = 0; } else { *cols = (int) wind_struct.ws_col; *rows = (int) wind_struct.ws_row; } } else (*X_Get_Term_Size_Hook)(cols, rows); if (*rows <= 0) *rows = *tt_Screen_Rows; if (*cols <= 0) *cols = *tt_Screen_Cols; #else if (X_Get_Term_Size_Hook == NULL) { *rows = *tt_Screen_Rows; *cols = *tt_Screen_Cols; } else (*X_Get_Term_Size_Hook)(cols, rows); #endif return 0; } /* returns 0 on failure, 1 on sucess */ int sys_delete_file(char *filename) { return(1 + unlink(filename)); } #ifdef __cplusplus #define SIGNAL(a,b) signal((a), (SIG_PF)(b)) #else #define SIGNAL signal #endif void sys_suspend(void) { SIGNAL (SIGTSTP, SIG_DFL); if (Signal_Sys_Spawn_Flag) kill(0, SIGSTOP); else kill(0, SIGTSTP); SIGNAL (SIGTSTP, sig_sys_spawn_cmd); } /* returns 0 if file does not exist, 1 if it is not a dir, 2 if it is */ int sys_chmod(char *file, int what, int *mode, short *uid, short *gid) { struct stat buf; int m; if (what) { chmod(file, *mode); chown(file, (uid_t) *uid, (uid_t) *gid); return(0); } if (stat(file, &buf) < 0) switch (errno) { case EACCES: return(-1); /* es = "Access denied."; break; */ case ENOENT: return(0); /* ms = "File does not exist."; */ case ENOTDIR: return(-2); /* es = "Invalid Path."; */ default: return(-3); /* "stat: unknown error."; break;*/ } m = buf.st_mode; *uid = buf.st_uid; *gid = buf.st_gid; /* AIX requires this */ #ifdef _S_IFDIR #ifndef S_IFDIR #define S_IFDIR _S_IFDIR #endif #endif #ifndef S_ISDIR # ifdef S_IFDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # else # define S_ISDIR(m) 0 # endif #endif *mode = m & 0777; if (S_ISDIR(m)) return (2); return(1); } unsigned long sys_file_mod_time(char *file) { struct stat buf; if (stat(file, &buf) < 0) return(0); return((unsigned long) buf.st_mtime); } /* use berkeley interface * #include <sys/dir.h> */ static char Found_Dir[256]; static char Found_File[256]; static int File_Len; #if HAVE_DIRENT_H # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # define NEED_D_NAMLEN # if HAVE_SYS_NDIR_H # include <sys/ndir.h> # endif # if HAVE_SYS_DIR_H # include <sys/dir.h> # endif # if HAVE_NDIR_H # include <ndir.h> # endif #endif static DIR *Dirp; /* These routines should be fixed to work with wildcards like the DOS and VMS * versions do. Unfortunately, it is a sad fact of life that Unix does NOT * support wildcards. Strangely enough, most Unix users are totally unaware * of this fact. * * To add wild card support, I need to use the regular expression package. * Specifically, in sys_findfirst, I would need to scan the file spec for * wild cards making the replacements: . --> \., ? -> ., and * -> .* in that * order. I should also quote the special characters ($, etc...) but I will * not worry about this. Finally, I will have to prefix it with '^' since * the match will start at the beginning of the string. * * Remark: to implement something like a real wildcard file renaming routine * would requires even more processing. Consider something like: * rename *.c~ *.bak * This mean that the first expression (*.c~) would have to be converted to: * \(.*\)\.c~ * and the second (*.bak) would be determined to be: \1.bak where \1 is * the expression matched by the first wildcard. * * After converting the wildcard file name to a regexp file name, I would then * have to compile it and save the compiled expression for use in sys_findnext. * There, I would use the regexp string matching routine instead of the * strcmp which is now used. * * Mainly, the findfirst/findnext are used by the completion routines. This * means that there is an implicit '.*' attached to the end of the filespec. * This will have to be dealt with. */ int sys_findnext(char *file) { struct dirent *dp; while (1) { if (NULL == (dp = readdir(Dirp))) return(0); #ifdef NEED_D_NAMLEN dp->d_name[dp->d_namlen] = 0; #endif if (!strncmp(Found_File, dp->d_name, File_Len)) break; } strcpy(file, Found_Dir); strcat(file, dp->d_name); if (2 == file_status(file)) strcat(file, "/"); return(1); } int sys_findfirst(char *the_file) { char *f, *file; file = expand_filename(the_file); f = extract_file(file); strcpy (Found_Dir, file); strcpy (Found_File, f); File_Len = strlen(f); Found_Dir[(int) (f - file)] = 0; if (Dirp != NULL) closedir(Dirp); if (NULL == (Dirp = (DIR *) opendir(Found_Dir))) return(0); strcpy(the_file, file); return sys_findnext(the_file); } /* This should be made available as part of the slang library */ #include <pwd.h> void get_passwd_info (char *name) { struct passwd *pwent; char *password = NULL; char *dir = NULL; char *shell = NULL; int uid = -1, gid = -1; if (*name == 0) { name = getlogin (); if (name == NULL) name = getenv ("LOGNAME"); if (name == NULL) name = getenv ("USER"); } if ((name != NULL) && ((pwent = getpwnam (name)) != NULL)) { password = pwent->pw_passwd; uid = pwent->pw_uid; gid = pwent->pw_gid; dir = pwent->pw_dir; shell = pwent->pw_shell; } if (password == NULL) password = ""; if (dir == NULL) dir = ""; if (shell == NULL) shell = ""; (void) SLang_push_string (dir); (void) SLang_push_string (shell); (void) SLang_push_string (password); (void) SLang_push_integer (uid); (void) SLang_push_integer (gid); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.