⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apmsleep.c

📁 电源管理程序
💻 C
字号:
/* apmsleep.c: * Suspend computer using APM and wake-up at given time using  * the Real Time Clock (RTC) device.  * * see man page apmsleep.1 for further details *  * Possible applications: *     - Run certain internet lookup programs at certain times *       e.g. download email, news, etc. *     - Send Faxes at night, but do not run laptop all night *     - Start up in the morning to catch up old cron jobs *  * Hint: *     use 'date' to calculate suspend time including daylight saving *     time correction. * * Possible future extensions (anyone?): *     - correct handling daylight saving time jumps *     - Set/restore '/dev/nvram' to set 'suspend to dram' option *     - apmcron job scheduler to add flexibility * *      Based on Paul Gortmacher's RTC Test/Example Program *	Copyright (C) 1999, Peter Englmaier <ppe@mpe.mpg.de> * *	Released under the GNU General Public License, version 2, *	included herein by reference. * * $Log: apmsleep.c,v $ * Revision 1.1  1999/08/02 20:08:08  apenwarr * * * Integrated apmsleep, and added xbattery (but without Makefile support). * * Revision 0.5  1999/08/01 01:29:29  ppe * Now using the apm library * * Revision 0.4  1999/07/19 16:45:29  ppe * *** empty log message *** *  * Revision 0.3  1999/07/19 16:10:38  ppe * Bug in wakeup time calculation corrected. * */#include <stdio.h>#include <linux/version.h>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)#include <asm/spinlock.h>#endif#include <linux/mc146818rtc.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <getopt.h>#include <sys/wait.h>#include <time.h>#include <apm.h>static char rcsid[]="$Id: apmsleep.c,v 1.1 1999/08/02 20:08:08 apenwarr Exp $";static char rcsrev[] = "$Revision: 1.1 $";void version() {  printf("Version: %s (apmsleep 1.2)\n",rcsrev);}void usage() {  printf("Usage:\n\n"	 "apmsleep [+]hh:mm\n\n"	 "Example:\n"	 "   apmsleep +1:15    will suspend for one hour and 15 minutes\n"	 "   apmsleep 8:00     will suspend until 8:00 am\n\n"	 "Bugs: Daylight saving jumps are not taken into account.\n"	 "      Modem ring detection may trigger early wake-up.\n"	 "      Does not work with Suspend to Disk.\n"	 "Bug reports to author Peter Englmaier <ppe@mpe.mpg.de>.\n");}int main(int argc, char **argv){  int i, rtcfd, retval;  struct rtc_time rtc_tm;  struct tm kernel_tm;  time_t kernel_time, new_time, old_time;  char *p, c;  int apmfd=-1;       /* APM device file descriptor */  int isoffset;       /* setting time offset */  int hour, minute;   /* alarm time requested */  int hour1, minute1;  /* backup for precise_mode */  int flag;  static int suspend_mode=0, wait_mode=0, debug_mode=0, precise_mode=0,    noapm_mode=0;  while (1) {    /* int this_option_optind = optind ? optind : 1; */    int option_index = 0;    static struct  option long_options[] = {      {"help",    0, 0, 'h'},      {"debug",   0, 0, 'd'},      {"version", 0, 0, 'V'},      {"suspend", 0, 0, 's'},      {"standby", 0, 0, 'S'},      {"wait",    0, 0, 'w'},      {"noapm",   0, 0, 'n'},      {"precise",   0, 0, 'p'},      {0,0,0,0}    };    c = getopt_long(argc, argv, "hdVsSwnp", long_options, &option_index);    if (c == -1) break;    switch(c)      {      case 'h':	usage();        exit(0);      case 'V':	version();        exit(0);      case 'd':	debug_mode=1;	break;      case 's': /*suspend*/	suspend_mode=0;	break;      case 'S': /*standby*/	suspend_mode=1;	break;      case 'n': /*noapm*/	noapm_mode=1;	wait_mode=1;	break;      case 'w':	wait_mode=!precise_mode;	break;      case 'p':/*precise*/	precise_mode=1;	break;      case '?': /*unknown option*/	exit(1);      default:	fprintf(stderr,"unknown option return %d\n", c);	exit(1);      }  } /* end while (1) */  if (optind < argc) {    if (optind+1 != argc) {      fprintf(stderr,"To many arguments.\n"); usage();      exit(1);    }    p=argv[optind];    isoffset=0;    if (p[0]=='+') { p++; isoffset=1;}    if (2!=sscanf(p, "%d:%d", &hour, &minute)) {      fprintf(stderr,"apmsleep: Bad argument(s)\n");      exit(1);    }    hour1=hour; minute1=minute; /* backup */  } else {    fprintf(stderr,"apmsleep: missing argument.\n"); usage();    exit(1);  }  if (noapm_mode) suspend_mode=2;  /* argument processing finished */  if (geteuid()!=0) {    fprintf(stderr, "apmsleep: warning: This program must be run as root "	      "or have the SUID attribute set\n");        }  /* check if APM is supported */  if (apm_exists()) {    fprintf(stderr, "apmsleep: Your kernel does not support APM.\n");    fprintf(stderr, "apmsleep: Recompile kernel with APM and "	    "/dev/rtc support\n");    exit(1);  }  if (!noapm_mode) {    apmfd=apm_open();    if (apmfd == -1) {      fprintf(stderr, "apmsleep: Cannot open APM device.\n");      exit(1);    }  }  rtcfd = open ("/dev/rtc", O_RDONLY);  if (errno == EACCES) {    fprintf(stderr, "apmsleep: You don't have permission to "	    "access /dev/rtc\n");          fprintf(stderr, "apmsleep: The program must be run as root "	    "or have the SUID attribute set\n");          exit(errno);  }  if (rtcfd ==  -1) {    perror("/dev/rtc");    fprintf(stderr, "apmsleep: Your kernel does not support "	    "the real time clock device\n");    fprintf(stderr, "apmsleep: Recompile kernel with APM and "	    "/dev/rtc support\n");    exit(errno);  }    /* Read the RTC time/date */  retval = ioctl(rtcfd, RTC_RD_TIME, &rtc_tm);  if (retval == -1) {    perror("ioctl");    exit(errno);  }  /* Read Kernel time/date */  time(&kernel_time);  kernel_tm=*localtime(&kernel_time);    if (debug_mode) {    printf("Current RTC time is %02d:%02d:%02d.\n",	   rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);    printf("Current local time is %02d:%02d:%02d.\n",	   kernel_tm.tm_hour, kernel_tm.tm_min, kernel_tm.tm_sec);  }  /* set alarm time in RTC */  if (isoffset) {    hour+=(int)rtc_tm.tm_hour;    minute+=(int)rtc_tm.tm_min;    hour1+=(int)kernel_tm.tm_hour;    minute1+=(int)kernel_tm.tm_min;  } else {    rtc_tm.tm_sec=0;    /* here we take difference between RTC and localtime into account */    minute+=(int)rtc_tm.tm_min - (int)kernel_tm.tm_min;    hour+=(int)rtc_tm.tm_hour - (int)kernel_tm.tm_hour;  }  while (minute<0) {minute +=60; hour--; }  while (minute>=60) {minute -=60; hour++; }  hour %= 24;  rtc_tm.tm_min = minute;  rtc_tm.tm_hour = hour;  if (debug_mode)    printf("Setting RTC alarm time to %02d:%02d:%02d.\n",	   hour, minute, rtc_tm.tm_sec);  retval = ioctl(rtcfd, RTC_ALM_SET, &rtc_tm);  if (retval == -1) {    perror("ioctl");    exit(errno);  }  /* Read back the current alarm settings */  retval = ioctl(rtcfd, RTC_ALM_READ, &rtc_tm);  if (retval == -1) {    perror("ioctl");    exit(errno);  }  if (debug_mode)     printf("RTC alarm time now set to %02d:%02d:%02d.\n",	   rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);    /* Enable alarm interrupts */  retval = ioctl(rtcfd, RTC_AIE_ON, 0);  if (retval == -1) {    perror("ioctl");    exit(errno);  }  /* Save time before suspending */  time(&new_time);  kernel_time=new_time;  if (fork()==0) {    /* suspend system -- called from within a child, to make     * sure we don't miss the time leap     */    switch(suspend_mode) {    case 0:      apm_suspend(apmfd);      break;    case 1:      apm_standby(apmfd);      break;    }    exit(0);  }  if (debug_mode) {    printf("Waiting until clock jumps\n");    fflush(stdout);  }  flag=1;  /* Note: flag is used as exit value */  if (precise_mode) {    /* wait for clock match alarm time */    if (debug_mode) printf("Wait for wakeup time\n");    do {      int diff;      /* Read Kernel time/date */      time(&kernel_time);      kernel_tm=*localtime(&kernel_time);      if (debug_mode) 	printf("Time: %02d:%02d:%02d, wakeup time: %02d:%02d:%02d\n",	       kernel_tm.tm_hour, kernel_tm.tm_min, kernel_tm.tm_sec,	       hour1, minute1, 0);      diff= hour1*60 + minute1 - kernel_tm.tm_hour*60 - kernel_tm.tm_min;      diff %= (24*60);      flag=(diff!=0 && diff!=-1);      if (flag) sleep(10);    } while (flag);  } else {    /* wait for the actual sleep event */    do {      old_time=new_time;      sleep(2);      time(&new_time);      flag=difftime(new_time,old_time)<10.0;      /* check for time out */      if (flag && wait_mode==0 && difftime(new_time,kernel_time)>120.0)	break; /* timeout, flag is 1 */    } while (flag);    if (flag)       fprintf(stderr,"Time out -- no time leap happened\n");    else if (debug_mode)      printf("Time leap detected\n");  }  /* Waiting for child to finish */  wait(&i);  /* Disable alarm interrupts */  retval = ioctl(rtcfd, RTC_AIE_OFF, 0);  if (retval == -1) {    perror("ioctl");    exit(errno);  }  close(rtcfd);  if (!noapm_mode) close(apmfd);    return flag;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -