home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / MM1 / GRAPHICS / ssaver.lzh / SRC / ssaver.c < prev   
C/C++ Source or Header  |  1995-11-04  |  15KB  |  763 lines

  1. /* K-Windows Screen Saver Master Program */
  2.  
  3. /* uses _gs_active() to get active flag status - bgp 4/13/95 */
  4.  
  5. #include <stdio.h>
  6. #include <types.h>
  7. #include <ctype.h>
  8. #include <modes.h>
  9. #include <mouse.h>
  10. #include <wind.h>
  11. #include <sgstat.h>
  12.  
  13. #include "saver.h"
  14.  
  15. #define TIMER_SIG 254
  16. #define MOUSE_SIG 253
  17.  
  18. void screensaver();
  19.  
  20. int  childWindow  = -1;
  21. int  gotsig       = FALSE;
  22. int  got_msig     = FALSE;
  23.  
  24. int  quit          = FALSE;    /* exit flag */
  25. int  password      = FALSE;    /* should we do locking? (Password prompt) */
  26. int  locked          = FALSE;    /* flag to tell us we've locked the screen */
  27. int  cycle_savers = TRUE;    /* flag to tell to cycle screensavers */
  28. int  force_event  = FALSE;
  29.  
  30. /* Times for different events to occur */
  31.  
  32. /* delay between changing screensavers - default 5 minutes */
  33. int  cycle_delay = 5 * 60;
  34. /* delay after activation to lock screen - default immediatly */
  35. int  lock_delay  = 0;
  36. /* seconds of inactivity befor starting screensaver - default 10 minutes */
  37. int  init_delay  = 10 * 60;
  38.  
  39. MSRET ms;
  40. int   evID;
  41. char  saver[128];
  42.  
  43. extern int errno;
  44.  
  45. char *helpmsg[] = {
  46.     "Syntax: SSaver [<opts>]\n",
  47.     "Function: K-Windows screen saver\n",
  48.     "Options:\n",
  49.     "   -a[=][<n>]   activate after 'n' minutes\n",
  50.     "                   (default = 10)\n",
  51.     "   -c[=][<n>]   cycle savers every 'n' minutes\n",
  52.     "                   (default = 5) 0 = never\n",
  53.     "   -l[=][<n>]   lock screen 'n' minutes after activation\n",
  54.     "                   (default = 0 or lock immediatly)\n",
  55.     "   -f           force - startup even if event already exists\n",
  56.     "\n",
  57.     NULL
  58. };
  59.  
  60. usage()
  61. {
  62.     int i = 0;
  63.  
  64.     while (helpmsg[i])
  65.         fputs(helpmsg[i++],stderr);
  66.     cleanup(0);
  67. }
  68.  
  69. int sig_trap(sig)
  70. int sig;
  71. {
  72.     if (sig == TIMER_SIG)
  73.         gotsig++;        /* increment our timer */
  74.  
  75.     if (sig == MOUSE_SIG)
  76.         got_msig = TRUE;
  77.  
  78.     if (sig == 2 || sig == 3 || sig == 9)
  79.         quit = TRUE;    /* someone trying to kill us */
  80. }
  81.  
  82. getoptions(argc, argv)
  83. int  argc;
  84. char **argv;
  85. {
  86.     register int     j, i;            /* Temp variables */
  87.     int             tempint;
  88.     char            *ptr,             /* temp pointer */
  89.                     *scan;            /* pointer */
  90.  
  91.     i = 1;
  92.     
  93.     for (i = 1; i < argc; i++)
  94.     {
  95.         ptr = argv[i];
  96.     
  97.         if (ptr[0] == '-')
  98.         {
  99.             scan = &ptr[1];
  100.             while (*scan != '\0')
  101.             {
  102.                 switch(toupper(*scan)) {
  103.                 case 'A' :
  104.                     scan++;
  105.                     if (*scan == '=')
  106.                         scan++;
  107.                     if (*scan && (tempint = atoi(scan)) > 0)
  108.                         init_delay = tempint * 60;
  109.                     while (*scan)
  110.                         scan++;
  111.                     scan--;
  112.                     break;
  113.                 case 'C' :
  114.                     scan++;
  115.                     if (*scan == '=')
  116.                         scan++;
  117.                     if (*scan && (tempint = atoi(scan)) > 0)
  118.                         cycle_delay = tempint * 60;
  119.                     if (cycle_delay == 0)
  120.                         cycle_savers = FALSE;
  121.                     while (*scan)
  122.                         scan++;
  123.                     scan--;
  124.                     break;
  125.                 case 'F' :    
  126.                     force_event = TRUE;
  127.                     break;
  128.                 case 'L' :
  129.                     password = TRUE;
  130.                     scan++;
  131.                     if (*scan == '=')
  132.                         scan++;
  133.                     if (*scan && (tempint = atoi(scan)) > 0)
  134.                         lock_delay = tempint * 60;
  135.                     while (*scan)
  136.                         scan++;
  137.                     scan--;
  138.                     break;
  139.                 case '?' :    
  140.                 case 'H' :
  141.                     usage();
  142.                     break;
  143.                 default  :
  144.                     fprintf(stderr,"Unknown option '-%c'\n",*scan);
  145.                     usage();
  146.                 }
  147.                 scan++;
  148.             }
  149.         }
  150.     }
  151. }
  152.  
  153. main(argc, argv)
  154. int  argc;
  155. char **argv;
  156. {
  157.     int  wd;
  158.     char device[32];
  159.     int  i;
  160.  
  161.     /* get options here */
  162.     getoptions(argc,argv);
  163.  
  164.     /*
  165.      * get device name
  166.      *  - this is the ONLY getstat we do on our parent's path!
  167.      *    - do this as soon as possible!
  168.      */
  169.     _gs_devn(1, &device[1]);
  170.  
  171.     /* add slash to name */
  172.     device[0] = '/';
  173.  
  174.     /* open new path to device */
  175.     if ((wd = open(device, S_IREAD | S_IWRITE)) == -1) {
  176.         fprintf(stderr, "cannot open %s...\n", device);
  177.         exit(errno);
  178.     }
  179.  
  180.     if (isKWindowsDevice(wd) == 0) {
  181.         fprintf(stderr, "ssaver must be run from a K-Windows console\n");
  182.         exit(0);
  183.     }
  184.  
  185.     /* lower out priority */
  186.     setpr(getpid(),80);
  187.     
  188.     /* attempt to create event
  189.      * if it exists, then assume screen saver is already running
  190.      * and exit appropriately
  191.      */
  192.     if ((evID = _ev_creat(0, 0, 0, EV_NAME)) == -1) {
  193.         if (!force_event) {
  194.             fprintf(stderr, "screen saver already running.\n");
  195.             exit(0);
  196.         } else if ((evID = _ev_link(EV_NAME)) != -1) {
  197.             _ev_set(evID, 0, 0x8000);   /* wake up everybody */
  198.         } else {
  199.             fprintf(stderr, "can't create/link to event.\n");
  200.             exit(0);
  201.         }
  202.     }
  203.  
  204.     /* close and dup in/out/err paths */
  205.     for (i = 0; i < 3; i++)
  206.     {
  207.         close(i);
  208.         dup(wd);
  209.     }
  210.     close(wd);
  211.  
  212.     /* install our signal handler */
  213.     intercept(sig_trap);
  214.  
  215.     do {
  216.         quit = FALSE;
  217.         if (got_timeout())
  218.             screensaver();
  219.     } while (! quit);
  220.  
  221.     cleanup(0);
  222. }
  223.  
  224. get_password(path,procid)
  225. int path;
  226. int procid;
  227. {
  228.     int  x,y;
  229.     int  echo;
  230.     int  valid = FALSE;
  231.     char string[40];
  232.     struct sgbuf opts;
  233.  
  234.     kill(procid,SLEEP_SIG);
  235.  
  236.     tsleep(0x80000020);
  237.  
  238.     _gs_scsz(path,&x,&y);
  239.  
  240.     _gs_opt(path,&opts);
  241.     echo = opts.sg_echo;
  242.  
  243.     opts.sg_echo  = 0;
  244.     opts.sg_kbich = 0;
  245.     opts.sg_kbach = 0;
  246.     opts.sg_eofch = 0;
  247.  
  248.     _ss_opt(path,&opts);
  249.  
  250.     drain(path);
  251.  
  252.     MCurSw(path,0);
  253.     OWSet(path,1,(x-24)/2,(y-7)/2,24,7,255,0);
  254.     _ss_wset(path,WT_DBOX,0);
  255.     CurOff(path);
  256.  
  257.     CurXY(path,3,1);
  258.     write(path,"Screen is Locked",16);
  259.  
  260.     CurXY(path,4,3);
  261.     write(path,"Enter Password",14);
  262.  
  263.  
  264.     read_password(path,string,30);
  265.  
  266.     opts.sg_echo = echo;
  267.     _ss_opt(path,&opts);
  268.  
  269.     CurXY(path,0,3);
  270.     DelLine(path);
  271.  
  272.     CurXY(path,5,3);
  273.     write(path,"Verifying...",12);
  274.  
  275.     if (strcmp(string,"password") == 0) {
  276.         valid = TRUE;
  277.     }
  278.  
  279.     sleep(2);
  280.  
  281.     CurXY(path,0,3);
  282.     DelLine(path);
  283.  
  284.     switch(valid) {
  285.     case TRUE:        
  286.         CurXY(path,3,3);
  287.         write(path,"Unlocking Screen",16);
  288.         sleep(1);
  289.         break;
  290.     case FALSE:        
  291.         CurXY(path,7,3);
  292.         write(path,"Invalid",7);
  293.         sleep(2);
  294.         break;
  295.     }
  296.     OWEnd(path);
  297.     _gs_active(path);
  298.     kill(procid,WAKE_SIG);
  299.     sleep(1);
  300.     return (valid);
  301. }
  302.  
  303. read_password(path,buf,len)
  304. int  path;
  305. char *buf;
  306. int  len;
  307. {
  308.     int  currwin, thiswin;
  309.     int  numchars = 0;
  310.     int  done = FALSE;
  311.     int  prompt_time = 60;
  312.     int  timeout;
  313.     char ch;
  314.  
  315.     /* get our window device number */
  316.     _gs_wdev(path, &thiswin);
  317.  
  318.     /* mouse click flag */
  319.     got_msig = FALSE;
  320.  
  321.     /* set up a mouse signal */
  322.     _ss_msig(path,MOUSE_SIG);
  323.     
  324.     /* clear buf */
  325.     buf[0] = '\0';
  326.     
  327.     /* Loop till mouse click, newline is typed or we have len - 2 chars */
  328.     while (! done && numchars < len - 2)
  329.     {
  330.         /* clear ch */
  331.         ch = '\0';
  332.  
  333.         timeout = prompt_time * 256;
  334.         /* loop till there is data waiting or a mouse click */
  335.         while (_gs_rdy(path) <= 0 && ! got_msig)
  336.         {
  337.             /* force 'em back to our screen */
  338.             _gs_currscr(path,&currwin);          /* get the displayed device */
  339.  
  340.             if (currwin != thiswin)              /* if they are different */
  341.                 _ss_select(path, thiswin);    /* select this screen */
  342.             tsleep(0x80000020);
  343.  
  344.             timeout -= 0x20;                  /* decrement prompt timer  */
  345.             if (timeout <= 0)                  /* if no input in 1 minute */
  346.             {
  347.                 done = TRUE;                  /* go back to screen saver */
  348.                 break;
  349.             }
  350.         }
  351.  
  352.         /* if data ready, get a char */
  353.         if (_gs_rdy(path) > 0)
  354.         {
  355.             read(path,&ch,1);
  356.         }
  357.  
  358.         /* was the mouse clicked? */
  359.         if (got_msig)
  360.         {
  361.             done = TRUE;
  362.         }
  363.  
  364.         switch(ch) {
  365.         case '\x0':            /* nothing typed */
  366.             break;
  367.         case '\x0d':
  368.         case '\x0a':
  369.             done = TRUE;
  370.             break;
  371.         case '\x7f':        /* del char */
  372.         case '\x08':        /* backspace */
  373.             if (numchars)
  374.                 numchars--;
  375.             buf[numchars] = '\0';
  376.             break;
  377.         case '\x15':    /* Ctrl-U */
  378.         case '\x18':    /* Ctrl-X */
  379.             numchars = 0;
  380.             buf[numchars] = '\0';
  381.             break;
  382.         default:
  383.             if (isprint(ch))   /* is it printable? */
  384.             {
  385.                 buf[numchars] = ch;
  386.                 numchars++;
  387.                 buf[numchars] = '\0';
  388.             }
  389.         }
  390.     }
  391.  
  392.     if (!got_msig)        /* if no mouse was clicked, */
  393.         _ss_rel(path);    /* release pending signal */
  394.     got_msig = FALSE;    /* reset mouse signal flag */
  395. }
  396.  
  397.     
  398. int active()
  399. {
  400.     /* never activate if we have gotten input */
  401.     if (_gs_active(STDOUT))
  402.         return(TRUE);
  403.  
  404.     _gs_mous(STDOUT, &ms);        /* get mouse position */
  405.  
  406.     /* never activate if mouse_x != 0 and mouse_y == 0 */
  407.     if (ms.pt_acx != 0 && ms.pt_acy == 0)
  408.         return(TRUE);
  409.  
  410.     return (FALSE);
  411. }
  412.  
  413. void reset_timer()
  414. {
  415.     _gs_mous(STDOUT, &ms);
  416.  
  417.     gotsig = 0;
  418.     /* activate if mouse_x == 0 && mouse_y == 0 */
  419.     if (ms.pt_acx | ms.pt_acy)
  420.         return;                    /* our timer is 0 */
  421.  
  422.     gotsig = init_delay;            /* activate we're at the hot spot */
  423. }
  424.  
  425. int forkSaver()
  426. {
  427.     int cid;
  428.     int orgStdin, orgStdout, orgStderr;
  429.     char *argv[2];
  430.     extern char **environ;
  431.     extern int os9forkc();
  432.  
  433.     /* choose a screen saver */
  434.     if (chooseSaver(saver) == 0) {
  435.         strcpy(saver, "saver_black");
  436.     }
  437.  
  438.     argv[0] = saver;
  439.     argv[1] = NULL;
  440.  
  441.     if (childWindow == -1) {
  442.         /* open path to new window -- child will _ss_select() its window */
  443.         if ((childWindow = open("/w", S_IWRITE | S_IREAD)) == -1) {
  444.             /* error opening new window */
  445.             return(-1);
  446.         }
  447.     }
  448.  
  449.     /* duplicate paths */
  450.     orgStdin = dup(0);
  451.     orgStdout = dup(1);
  452.     orgStderr = dup(2);
  453.  
  454.     /* close paths */
  455.     close(0);
  456.     dup(childWindow);
  457.     close(1);
  458.     dup(childWindow);
  459.     close(2);
  460.     dup(childWindow);
  461.  
  462.     /* set the event value to 1 so that we may wait until our child
  463.      * uses _ev_signal()
  464.      */
  465.     _ev_set(evID, 1, 0);
  466.  
  467.     /* fork screen saver */
  468.     cid = os9exec(os9forkc, argv[0], argv, environ, 0, 0, 3);
  469.  
  470.     /* restore paths */
  471.     close(0);
  472.     dup(orgStdin);
  473.     close(1);
  474.     dup(orgStdout);
  475.     close(2);
  476.     dup(orgStderr);
  477.  
  478.     /* close extra paths */
  479.     close(orgStdin);
  480.     close(orgStdout);
  481.     close(orgStderr);
  482.  
  483.     /* wait for child to start up completely */
  484.     while (_ev_wait(evID, 0, 0) != 0);
  485.  
  486.     /* return child ID */
  487.     return(cid);
  488. }
  489.  
  490. /*
  491.  * Wait till the key/mouse is inactive for 'timeout' seconds
  492.  *
  493.  * RETURNS:
  494.  *    TRUE if keyboard and mouse have timed out
  495.  *    FALSE if quit signal was recieved
  496.  */
  497. int got_timeout()
  498. {
  499.     int id;
  500.  
  501.     /* clear gotsig */
  502.     gotsig = 0;
  503.  
  504.     /* set alarm every second */
  505.     if ((id = alm_cycle(TIMER_SIG,0x80000100)) == -1) {
  506.         cleanup(errno);
  507.     }
  508.  
  509.     do {
  510.         sleep(0);
  511.  
  512.         if (active())    /* if our flag is set */
  513.             reset_timer();
  514.     } while (gotsig < init_delay && ! quit);
  515.  
  516.     /* delete the alarm */
  517.     alm_delete(id);
  518.  
  519.     /* was the timer reached? or did we get a kill signal? */
  520.     return((quit) ? FALSE : TRUE);
  521. }
  522.  
  523. /* fork off our pretty pictures, etc. */
  524. void screensaver()
  525. {
  526.     int  cid;            /* child ID */
  527.     int  is_active;
  528.     int  cycle_time = cycle_delay * 256;
  529.     int  lock_time;
  530.     char ch;
  531.  
  532.     /* at this point we fork the screen saver */
  533.     if ((cid = forkSaver()) == -1)
  534.         return;
  535.  
  536.     locked = FALSE;
  537.     
  538.     if (password == TRUE)
  539.         lock_time = lock_delay * 256;
  540.  
  541.     do {
  542.         /* decrement out time for this screensaver to live */
  543.         tsleep(0x80000020);
  544.  
  545.         /* check to see if we should get a password */
  546.         if (! locked && password == TRUE) {
  547.             lock_time -= 0x20;    /* decrement time till password required */
  548.             if (lock_time <= 0) /* is it time? */
  549.                 locked = TRUE;  /* yep, need a password now */
  550.         }
  551.  
  552.         /* are we cycling screensavers? */
  553.          if (cycle_savers == TRUE)
  554.          {
  555.             cycle_time -= 0x20;    /* decrement cycle time by our last sleep */
  556.              if (cycle_time <= 0)/* is it time? */
  557.             {
  558.                 kill(cid,QUIT_SIG);            /* Tell saver_xxx to shutdown */
  559.                 while (cid != wait(0));     /* Wait for it to exit */
  560.  
  561.                 /* drain any pending characters */
  562.                 drain(childWindow);
  563.  
  564.                 /* reset window to undefined for next screensaver */
  565.                 DWEnd(childWindow);
  566.  
  567.                 /* invoke the next screensaver */
  568.                 if ((cid = forkSaver()) == -1)
  569.                     return;
  570.  
  571.                 /* reset cycle_time */
  572.                 cycle_time = cycle_delay * 256;
  573.             }
  574.         }
  575.  
  576.         /* grab the active flag */
  577.         is_active = _gs_active(STDOUT);
  578.             
  579.         /* if active and we what a password to unlock */
  580.         if (is_active && locked)
  581.             is_active = get_password(childWindow,cid);
  582.  
  583.     } while (! is_active && ! quit);
  584.  
  585.     /* Send a signal to the program to quit */
  586.     kill(cid, QUIT_SIG);
  587.     while (cid != wait(0));
  588.  
  589.     /* drain any pending characters */
  590.     drain(childWindow);
  591.  
  592.     /* close our path to child's window */
  593.     close(childWindow);
  594.     childWindow = -1;
  595. }
  596.  
  597. drain(path)
  598. int path;
  599. {
  600.     char ch;
  601.  
  602.     /* drain any pending characters */
  603.     while(_gs_rdy(path) > 0)
  604.         read(path,&ch,1);
  605. }    
  606.  
  607. cleanup(code)
  608. int code;
  609. {
  610.     _ev_unlink(evID);            /* unlink the event */
  611.     _ev_delete(EV_NAME);            /* delete the event */
  612.     exit(code);
  613. }
  614.  
  615. /* this function reads the ssaver.list file in search of a
  616.  * screen saver program to run for this incarnation.
  617.  *
  618.  * Returns:
  619.  *       0 - can't open ssaver.list
  620.  *       1 - everything's OK
  621.  */
  622. int chooseSaver(saver_name)
  623. char *saver_name;
  624. {
  625.     int dpath, t, e;
  626.     char text[128];
  627.  
  628.     dpath = open("/dd/sys/ssaver.list", S_IREAD);
  629.     if (dpath == -1)
  630.     {
  631.         dpath = open("/dd/sys/.ssaver.list", S_IREAD);
  632.         if (dpath == -1) return(0);
  633.     }
  634.     t = 0;
  635.     while(1)
  636.     {
  637.         if (readln(dpath, text, 80) < 1) break;
  638.         if (isalpha(text[0]) || text[0]=='/') t++;
  639.     }
  640.     e = rrand(t);
  641.     lseek(dpath, 0, 0);
  642.     t = 0;
  643.     while(t < e)
  644.     {
  645.         readln(dpath,text,80);
  646.         if (isalpha(text[0]) || text[0] == '/') t++;
  647.     }
  648.     strcpy(saver_name, text);
  649.     close(dpath);
  650.     return(1);
  651. }
  652.  
  653. static int rndval = 100000;        /* BGP */
  654.  
  655. /* rrand( val ) : return a pseudo-random value between 1 and val.
  656. **               IF val is -1, it is used as a seed.
  657. **               IF val is negative the better the seed.
  658. */
  659. rrand( val )
  660. int val;
  661. {
  662.     int bit0, bit1, bit14, num, i;
  663.  
  664.     /* see if -1 */
  665.     if ( val < 0 ) {
  666.         rndval = -val;
  667.     }
  668.  
  669.     for ( i = 0; i < 10; i++ )
  670.     {
  671.         bit0 = rndval & 1;
  672.         bit1 = (rndval & 2) >> 1;
  673.         bit14 = bit0 ^ bit1;
  674.         rndval >>=1;
  675.         rndval |= (bit14 << 14);
  676.     }
  677.     num = rndval % val;
  678.     return( num ? num : val );
  679. }
  680.  
  681.  
  682. /*
  683.  * this function returns 1 if the current path is open
  684.  * under a K-Windows device, else it returns 0
  685.  *
  686.  * Boisy G. Pitre -- 12/8/94
  687.  */
  688.  
  689. #include <module.h>
  690.  
  691. isKWindowsDevice(path)
  692. int path;
  693. {
  694.     char device[32], driver[8];
  695.     mod_dev *descAddr;
  696.  
  697.     /* get the name of the path's device */
  698.     if (_gs_devn(path, device) == -1) {
  699.         /* failed to get device */
  700.         return(0);
  701.     }
  702.  
  703.     /* attempt to link to path's device ONLY if it's a descriptor */
  704.     if ((descAddr = modlink(device, mktypelang(MT_DEVDESC, ML_ANY))) == -1) {
  705.         /* failed to link to path's device */
  706.         return(0);
  707.     }
  708.  
  709.     munlink(descAddr);    /* unlink to be nice */
  710.  
  711.     /* copy driver string and check to see if it's windio */
  712.     strncpy(driver, (int)descAddr + descAddr->_mpdev, 6);
  713.     driver[6] = '\0';
  714.     if (strucmp(driver, "WINDIO") != 0) {
  715.         return(0);
  716.     }
  717.  
  718.     /* it's more than likely a K-Windows window */
  719.     return(1);
  720. }
  721.  
  722.  
  723. int strucmp (str1, str2)
  724. register char *str1, *str2;
  725. {
  726.      register char *p;
  727.  
  728.      if ((p = index (str1,'\n')) != NULL)   *p ='\0';
  729.      if ((p = index (str2,'\n')) != NULL)   *p ='\0';
  730.  
  731.      while (toupper (*str1) == toupper (*str2) && *str1 && *str2) {
  732.           ++str1;
  733.           ++str2;
  734.      }
  735.  
  736.      if (*str1 == *str2)  return(0);
  737.      if (*str1 > *str2)   return(1);
  738.      return(-1);
  739. }
  740.  
  741.  
  742. /*
  743.  * this function returns the edition number of windio
  744.  * or -1 if the windio driver cannot be found
  745.  *
  746.  * Boisy G. Pitre -- 12/8/94
  747.  */
  748.  
  749. int KWindowsEdition()
  750. {
  751.     struct modhcom *windioDrv;
  752.  
  753.     /* attempt to link to windio driver */
  754.     if ((windioDrv = modlink("windio", mktypelang(MT_DEVDRVR, ML_ANY))) == -1) {
  755.         /* failed to link to windio driver */
  756.         return(-1);
  757.     }
  758.  
  759.     munlink("windio");    /* unlink to be nice */
  760.  
  761.     return((int)windioDrv->_medit);
  762. }
  763.