home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / src / unix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  11.3 KB  |  458 lines

  1. /*
  2.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "config.h"
  8. #include "sysdep.h"
  9.  
  10. #include <signal.h>
  11. /* sequent support thanks to Kenneth Lorber <keni@oasys.dt.navy.mil> */
  12. /* SYSV (SYSV ISC R3.2 v3.0) provided by iain.lea@erlm.siemens.de */
  13.  
  14. #include <sys/time.h>
  15. #include <sys/ioctl.h>
  16. #ifndef sequent
  17. # include <termios.h>
  18. #endif
  19.  
  20. #ifdef SYSV
  21. # ifndef CRAY
  22. #   include <sys/termio.h>
  23. #   include <sys/stream.h>
  24. #   include <sys/ptem.h>
  25. #   include <sys/tty.h>
  26. # endif
  27. #endif
  28.  
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <errno.h>
  32.  
  33. #define TTY_DESC 2
  34. static int Read_FD = TTY_DESC;
  35. int Flow_Control;
  36. int Abort_Char = 7;               /* scan code for G (control) */
  37.  
  38.  
  39. #ifdef sequent
  40. struct ttystuff
  41.   {
  42.       struct tchars t;
  43.       struct ltchars lt;
  44.       struct sgttyb s;
  45.   };
  46. struct ttystuff OLDTTY;
  47. #else
  48. struct termios OLDTTY;
  49. #endif
  50.  
  51.      /* this next works on ultrix for setting termios */
  52. #ifdef TCGETS
  53. #define GET_TERMIOS(fd, x) ioctl(fd, TCGETS, x)
  54. #define SET_TERMIOS(fd, x) ioctl(fd, TCSETS, x)
  55. #else
  56. # ifdef sequent
  57. #  define X(x,m)  &(((struct ttystuff*)(x))->m)
  58. #  define GET_TERMIOS(fd, x)    \
  59.     if(ioctl(fd, TIOCGETC, X(x,t))<0 || \
  60.     ioctl(fd, TIOCGLTC, X(x,lt))<0 || \
  61.     ioctl(fd, TIOCGETP, X(x,s))<0)exit_error("Can't get terminal info", 0)
  62. #  define SET_TERMIOS(fd, x)    \
  63.     if(ioctl(fd, TIOCSETC, X(x,t))<0 || \
  64.     ioctl(fd, TIOCSLTC, X(x,lt))<0 || \
  65.     ioctl(fd, TIOCSETP, X(x,s))<0)exit_error("Can't set terminal info", 0)
  66. # else
  67. #  define GET_TERMIOS(fd, x) tcgetattr(fd, x)
  68. #  define SET_TERMIOS(fd, x) tcsetattr(fd, TCSAFLUSH, x)
  69. /* #  define SET_TERMIOS(fd, x) tcsetattr(fd, TCSANOW, x) */
  70. # endif
  71. #endif
  72.  
  73. static int Baud_Rates[20] = 
  74. {
  75.    0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 
  76.    9600, 19200, 38400, 0, 0, 0, 0
  77. };
  78.  
  79.  
  80.  
  81. static int tty_inited = 0;
  82.  
  83. void init_tty()
  84. {
  85. #ifdef sequent
  86.     struct ttystuff newtty;
  87. #else
  88.     struct termios newtty;
  89. #endif
  90.  
  91.    if (Batch) return;
  92.    tty_inited = 1;
  93.    if (X_Init_Term_Hook != NULL)
  94.      {
  95.     Read_FD = (*X_Init_Term_Hook) ();
  96.     return;
  97.      }
  98.    
  99.    tt_enable_cursor_keys();
  100.    GET_TERMIOS(Read_FD, &OLDTTY);
  101.    GET_TERMIOS(Read_FD, &newtty);
  102. #ifdef sequent
  103.    newtty.s.sg_flags &= ~(ECHO);
  104.    newtty.s.sg_flags &= ~(CRMOD);
  105. /*   if (Flow_Control == 0) newtty.s.sg_flags &= ~IXON; */
  106.    newtty.t.t_eofc = 1;
  107.    newtty.t.t_intrc = Abort_Char;    /* ^G */
  108.    newtty.t.t_quitc = 255;
  109.    newtty.lt.t_suspc = 255;   /* to ignore ^Z */
  110.    newtty.lt.t_dsuspc = 255;    /* to ignore ^Y */
  111.    newtty.lt.t_lnextc = 255;
  112.    newtty.s.sg_flags |= CBREAK;        /* do I want cbreak or raw????? */
  113. #else
  114.    
  115.    if (*tt_Baud_Rate == 0)
  116.      {
  117. /* Note:  if this generates an compiler error, simply remove 
  118.    the statement */
  119.     *tt_Baud_Rate = cfgetospeed (&newtty);
  120.     
  121.     
  122.     *tt_Baud_Rate = (*tt_Baud_Rate > 0) && (*tt_Baud_Rate < 19) ?
  123.                   Baud_Rates[*tt_Baud_Rate] : -1;
  124.      }
  125.    
  126.    newtty.c_iflag &= ~(ECHO | INLCR | ICRNL);
  127. #ifdef ISTRIP
  128.    /* allow 8 bit chars to pass through */
  129.    newtty.c_iflag &= ~ISTRIP;
  130. #endif
  131.    newtty.c_oflag &= ~(ONLCR | OPOST);           /* do not map newline to cr/newline on out */
  132.    if (Flow_Control == 0) newtty.c_iflag &= ~IXON;
  133.    newtty.c_cc[VMIN] = 1;
  134.    newtty.c_cc[VTIME] = 0;
  135.    newtty.c_cc[VEOF] = 1;
  136.    newtty.c_lflag = ISIG | NOFLSH;
  137.  
  138.    newtty.c_cc[VINTR] = Abort_Char;   /* ^G */
  139.    newtty.c_cc[VQUIT] = 255;
  140.    newtty.c_cc[VSUSP] = 255;   /* to ignore ^Z */
  141. #ifdef VDSUSP
  142.    newtty.c_cc[VDSUSP] = 255;   /* to ignore ^Y */
  143. #endif
  144. #ifdef VSWTCH
  145.    newtty.c_cc[VSWTCH] = 255;   /* to ignore who knows what */
  146. #endif
  147. #endif /*sequent*/
  148.    SET_TERMIOS(Read_FD, &newtty);
  149. }
  150.  
  151. void reset_tty()
  152. {
  153.    if (Batch) return;
  154.    if (!tty_inited) return;
  155.    if (X_Init_Term_Hook != NULL)
  156.      {
  157.     if (X_Reset_Term_Hook != NULL) (*X_Reset_Term_Hook) ();
  158.     return;
  159.      }
  160.    
  161.    SET_TERMIOS(Read_FD, &OLDTTY);
  162.    /* This statement ensures init_tty will not try to change output_rate 
  163.       (when coming back from suspension) */
  164.    if (*tt_Baud_Rate == 0) *tt_Baud_Rate = -1;
  165. }
  166.  
  167. unsigned char sys_getkey()
  168. {
  169.    int n = 450;
  170.    int count = 10;
  171.    unsigned char c;
  172.    if (SLKeyBoard_Quit) return((int) Abort_Char);
  173.    /* sleep for 45 second and try again */
  174.    while (!SLKeyBoard_Quit && !sys_input_pending(&n))
  175.      {
  176.     /* update status line incase user is displaying time */
  177.     if (Display_Time)
  178.       {
  179.          JWindow->trashed = 1;
  180.          update((Line *) NULL, 0, 1);
  181.       }
  182.      }
  183.    if (SLKeyBoard_Quit) return(Abort_Char);
  184.  
  185.    if (X_Read_Hook != NULL) return (c = X_Read_Hook ());
  186.    
  187.    while (count-- && (read(Read_FD, &c, 1) < 0) && !SLKeyBoard_Quit) sleep(1);
  188.    
  189.    if (count <= 0)
  190.      {
  191.     exit_error ("getkey(): read failed", 0);
  192.      }
  193.  
  194.    /* only way for keyboard quit to be non zero is if ^G recived and sigint processed */
  195.    if (SLKeyBoard_Quit) c = Abort_Char;
  196.    SLKeyBoard_Quit = 0;
  197.    return(c);
  198. }
  199.   
  200. #ifndef FD_SET
  201. #define FD_SET(fd, tthis) *(tthis) = 1 << fd
  202. #define FD_ZERO(tthis)    *(tthis) = 0
  203. typedef int fd_set;
  204. #endif
  205.  
  206. static fd_set Read_FD_Set;
  207.  
  208. static int sys_input_pending(int *tsecs)
  209. {
  210.    struct timeval wait;
  211.    long usecs, secs;
  212.    int ret;
  213.  
  214.    if (Input_Buffer_Len || Batch) return(Input_Buffer_Len);
  215.    
  216.    
  217.    secs = *tsecs / 10;
  218.    usecs = (*tsecs % 10) * 100000;
  219.    wait.tv_sec = secs;
  220.    wait.tv_usec = usecs;
  221.    
  222.    if (X_Input_Pending_Hook != NULL) 
  223.      {
  224.     if ((*X_Input_Pending_Hook) ()) return 1;
  225.      }
  226.    
  227.    FD_SET(Read_FD, &Read_FD_Set);
  228.    ret = select(Read_FD + 1, &Read_FD_Set, NULL, NULL, &wait);
  229.    if (ret && (X_Input_Pending_Hook != NULL))
  230.      {
  231.     if ((*X_Input_Pending_Hook) ()) return 1;
  232.     /* Nothing there so try to time out again --- too bad select does
  233.      * not inform of of how far we got. */
  234.     FD_SET(Read_FD, &Read_FD_Set);
  235.     ret = select(Read_FD + 1, &Read_FD_Set, NULL, NULL, &wait);
  236.     /* try again, it could be more bogus Xpackets.  Event driven systems
  237.      * are not always the way to go. */
  238.     if (ret) return (*X_Input_Pending_Hook) ();
  239.      }
  240.    return (ret);
  241. }
  242.  
  243. /*  This is to get the size of the terminal  */
  244. void get_term_dimensions(int *cols, int *rows)
  245. {
  246. #ifdef TIOCGWINSZ
  247.    struct winsize wind_struct;
  248.  
  249.    if (X_Get_Term_Size_Hook == NULL)
  250.      {
  251.     if ((ioctl(2,TIOCGWINSZ,&wind_struct) < 0)
  252.         && (ioctl(0, TIOCGWINSZ, &wind_struct) < 0)
  253.         && (ioctl(1, TIOCGWINSZ, &wind_struct) < 0))
  254.       {
  255.          *rows = *cols = 0;
  256.       }
  257.     else
  258.       {
  259.          *cols = (int) wind_struct.ws_col;
  260.          *rows = (int) wind_struct.ws_row;
  261.       }
  262.      }
  263.    else (*X_Get_Term_Size_Hook)(cols, rows);
  264.  
  265.    if (*rows <= 0) *rows = *tt_Screen_Rows;
  266.    if (*cols <= 0) *cols = *tt_Screen_Cols;
  267. #else
  268.    if (X_Get_Term_Size_Hook == NULL)
  269.      {
  270.     *rows = *tt_Screen_Rows;
  271.     *cols = *tt_Screen_Cols;
  272.      }
  273.    else (*X_Get_Term_Size_Hook)(cols, rows);
  274. #endif
  275. }
  276.  
  277. /* returns 0 on failure, 1 on sucess */
  278. int sys_delete_file(char *filename)
  279. {
  280.     return(1 + unlink(filename));
  281. }
  282.  
  283. int sys_rename(char *from, char *to)
  284. {
  285.     return(rename(from,to));
  286. }
  287.  
  288. #ifdef SIGTSTP
  289. extern void sig_sys_spawn_cmd(int);
  290. extern int Signal_Sys_Spawn_Flag;      /* used if something else sends stop */
  291. #endif
  292.  
  293.  
  294. void sys_suspend(void)
  295. {   
  296.    signal (SIGTSTP, SIG_DFL);
  297.    if (Signal_Sys_Spawn_Flag) kill(0, SIGSTOP); else kill(0, SIGTSTP);
  298.    signal (SIGTSTP, sig_sys_spawn_cmd);   
  299. }
  300.  
  301.  
  302. /* ///////////////////////////////////////////////////////////////////
  303. //  Function:   int sys_System(char *command_line);
  304. //
  305. //  Descript:    a shell wrapper included for DOS compatability
  306. //        removes leading '!' and then uses system()
  307. //
  308. //  Returns:    returns error codes as per system()
  309. ///////////////////////////////////////////////////////////////////// */
  310.  
  311. int
  312. sys_System(char *command_line)
  313. {
  314.    while ( *command_line != '\0' && *command_line == ' ' )
  315.      command_line++;            /* start on 1st non-space */
  316.  
  317.    if ( *command_line == '!' ) {
  318.       command_line++;            /* advance past this '!' */
  319.       while ( *command_line != '\0' && *command_line == ' ' )
  320.           command_line++;            /* start on next non-space */
  321.    }
  322.    return system( command_line );
  323. }
  324.  
  325. /* returns 0 if file does not exist, 1 if it is not a dir, 2 if it is */
  326. int sys_chmod(char *file, int what, int *mode, short *uid, short *gid)
  327. {
  328.    struct stat buf;
  329.    int m;
  330.  
  331.    if (what)
  332.      {
  333.     chmod(file, *mode);
  334.     chown(file, (uid_t) *uid, (uid_t) *gid);
  335.     return(0);
  336.      }
  337.  
  338.    if (stat(file, &buf) < 0) switch (errno)
  339.      {
  340.     case EACCES: return(-1); /* es = "Access denied."; break; */
  341.     case ENOENT: return(0);  /* ms = "File does not exist."; */
  342.     case ENOTDIR: return(-2); /* es = "Invalid Path."; */
  343.     default: return(-3); /* "stat: unknown error."; break;*/
  344.      }
  345.  
  346.    m = buf.st_mode;
  347.    *uid = buf.st_uid;
  348.    *gid = buf.st_gid;
  349.    
  350. /* AIX requires this */
  351. #ifdef _S_IFDIR
  352. #ifndef S_IFDIR
  353. #define S_IFDIR _S_IFDIR
  354. #endif
  355. #endif
  356.  
  357.    *mode = m & 0777;
  358.  
  359.    if (m & S_IFDIR) return (2);
  360.    return(1);
  361. }
  362.  
  363. unsigned long sys_file_mod_time(char *file)
  364. {
  365.    struct stat buf;
  366.  
  367.    if (stat(file, &buf) < 0) return(0);
  368.    return((unsigned long) buf.st_mtime);
  369. }
  370.  
  371. /* use berkeley interface
  372.  * #include <sys/dir.h>
  373. */
  374.  
  375. static char Found_Dir[256];
  376. static char Found_File[256];
  377. static int File_Len;
  378.  
  379. #ifdef sequent
  380. # include <sys/dir.h>
  381. # define NEED_D_NAMLEN
  382. #else
  383. # include <dirent.h>
  384. #endif
  385.  
  386. static DIR *Dirp;
  387.  
  388. /* These routines should be fixed to work with wildcards like the DOS and VMS
  389.  * versions do.  Unfortunately, it is a sad fact of life that Unix does NOT
  390.  * support wildcards.  Strangely enough, most Unix users are totally unaware
  391.  * of this fact.
  392.  * 
  393.  * To add wild card support, I need to use the regular expression package.
  394.  * Specifically, in sys_findfirst, I would need to scan the file spec for 
  395.  * wild cards making the replacements: . --> \., ? -> ., and * -> .* in that
  396.  * order.  I should also quote the special characters ($, etc...) but I will
  397.  * not worry about this.  Finally, I will have to prefix it with '^' since
  398.  * the match will start at the beginning of the string.
  399.  * 
  400.  *    Remark: to implement something like a real wildcard file renaming routine
  401.  *    would requires even more processing.  Consider something like: 
  402.  *       rename *.c~ *.bak
  403.  *    This mean that the first expression (*.c~) would have to be converted to:
  404.  *      \(.*\)\.c~
  405.  *    and the second (*.bak) would be determined to be: \1.bak  where \1 is
  406.  *    the expression matched by the first wildcard.  
  407.  * 
  408.  * After converting the wildcard file name to a regexp file name, I would then
  409.  * have to compile it and save the compiled expression for use in sys_findnext.
  410.  * There, I would use the regexp string matching routine instead of the 
  411.  * strcmp which is now used.
  412.  * 
  413.  * Mainly, the findfirst/findnext are used by the completion routines.  This
  414.  * means that there is an implicit '.*' attached to the end of the filespec.
  415.  * This will have to be dealt with.
  416.  */
  417. int sys_findnext(char *file)
  418. {
  419. #ifdef NEED_D_NAMLEN
  420. #define dirent direct
  421. #endif
  422.  
  423.    struct dirent *dp;
  424.  
  425.    while (1)
  426.      {
  427.     if (NULL == (dp = readdir(Dirp))) return(0);
  428. #ifdef NEED_D_NAMLEN
  429.     dp->d_name[dp->d_namlen] = 0;
  430. #endif
  431.     if (!strncmp(Found_File, dp->d_name, File_Len)) break;
  432.      }
  433.    strcpy(file, Found_Dir); strcat(file, dp->d_name);
  434.    if (2 == file_status(file)) strcat(file, "/");
  435.    return(1);
  436. }
  437.  
  438.  
  439. int sys_findfirst(char *the_file)
  440. {
  441.    char *f, *file;
  442.  
  443.    file = expand_filename(the_file);
  444.    f = extract_file(file);
  445.  
  446.    strcpy (Found_Dir, file);
  447.    strcpy (Found_File, f);
  448.    File_Len = strlen(f);
  449.  
  450.    Found_Dir[(int) (f - file)] = 0;
  451.  
  452.    if (Dirp != NULL) closedir(Dirp);
  453.  
  454.    if (NULL == (Dirp = (DIR *) opendir(Found_Dir))) return(0);
  455.    strcpy(the_file, file);
  456.    return sys_findnext(the_file);
  457. }
  458.