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

📄 smartd.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    snprintf(command, 2048, "%s 2>&1", executable);    // tell SYSLOG what we are about to do...  newadd=address?address:"<nomailer>";  newwarn=which?"Warning via":"Test of";  PrintOut(LOG_INFO,"%s %s to %s ...\n",           which?"Sending warning via":"Executing test of", executable, newadd);    // issue the command to send mail or to run the user's executable  errno=0;  if (!(pfp=popen(command, "r")))    // failed to popen() mail process    PrintOut(LOG_CRIT,"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n", 	     newwarn,  executable, newadd, errno?strerror(errno):"");  else {    // pipe suceeded!    int len, status;    char buffer[EBUFLEN];    // if unexpected output on stdout/stderr, null terminate, print, and flush    if ((len=fread(buffer, 1, EBUFLEN, pfp))) {      int count=0;      int newlen = len<EBUFLEN ? len : EBUFLEN-1;      buffer[newlen]='\0';      PrintOut(LOG_CRIT,"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n", 	       newwarn, executable, newadd, len!=newlen?"here truncated to ":"", newlen, buffer);            // flush pipe if needed      while (fread(buffer, 1, EBUFLEN, pfp) && count<EBUFLEN)	count++;      // tell user that pipe was flushed, or that something is really wrong      if (count && count<EBUFLEN)	PrintOut(LOG_CRIT,"%s %s to %s: flushed remaining STDOUT/STDERR\n", 		 newwarn, executable, newadd);      else if (count)	PrintOut(LOG_CRIT,"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n", 		 newwarn, executable, newadd);    }        // if something went wrong with mail process, print warning    errno=0;    if (-1==(status=pclose(pfp)))      PrintOut(LOG_CRIT,"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,	       errno?strerror(errno):"");    else {      // mail process apparently succeeded. Check and report exit status      int status8;      if (WIFEXITED(status)) {	// exited 'normally' (but perhaps with nonzero status)	status8=WEXITSTATUS(status);		if (status8>128)  	  PrintOut(LOG_CRIT,"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n", 		   newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));	else if (status8)  	  PrintOut(LOG_CRIT,"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n", 		   newwarn, executable, newadd, status, status8);	else	  PrintOut(LOG_INFO,"%s %s to %s: successful\n", newwarn, executable, newadd);      }            if (WIFSIGNALED(status))	PrintOut(LOG_INFO,"%s %s to %s: exited because of uncaught signal %d [%s]\n", 		 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));            // this branch is probably not possible. If subprocess is      // stopped then pclose() should not return.      if (WIFSTOPPED(status))       	PrintOut(LOG_CRIT,"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",		 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));          }  }  #else // _WIN32  // No "here-documents" on Windows, so must use separate commandline and stdin  command[0] = stdinbuf[0] = 0;  boxtype = -1; boxmsgoffs = 0;  newadd = "<nomailer>";  if (address) {    // address "[sys]msgbox ..." => show warning (also) as [system modal ]messagebox    int addroffs = (!strncmp(address, "sys", 3) ? 3 : 0);    if (!strncmp(address+addroffs, "msgbox", 6) && (!address[addroffs+6] || address[addroffs+6] == ',')) {      boxtype = (addroffs > 0 ? 1 : 0);      addroffs += 6;      if (address[addroffs])        addroffs++;    }    else      addroffs = 0;    if (address[addroffs]) {      // Use "blat" parameter syntax (TODO: configure via -M for other mailers)      snprintf(command, sizeof(command),               "%s - -q -subject \"%s\" -to \"%s\"",               executable, subject, address+addroffs);      newadd = address+addroffs;    }    // Message for mail [0...] and messagebox [boxmsgoffs...]    snprintf(stdinbuf, sizeof(stdinbuf),             "This email was generated by the smartd daemon running on:\n\n"             "   host name: %s\n"             "  DNS domain: %s\n"//           "  NIS domain: %s\n"             "\n%n"             "The following warning/error was logged by the smartd daemon:\n\n"             "%s\n\n"             "For details see the event log or log file of smartd.\n\n"             "%s%s%s"             "\n",             hostname, /*domainname, */ nisdomain, &boxmsgoffs, message, further, original, additional);  }  else    snprintf(command, sizeof(command), "%s", executable);  newwarn=which?"Warning via":"Test of";  if (boxtype >= 0) {    // show message box    daemon_messagebox(boxtype, subject, stdinbuf+boxmsgoffs);    PrintOut(LOG_INFO,"%s message box\n", newwarn);  }  if (command[0]) {    char stdoutbuf[800]; // < buffer in syslog_win32::vsyslog()    int rc;    // run command    PrintOut(LOG_INFO,"%s %s to %s ...\n",             (which?"Sending warning via":"Executing test of"), executable, newadd);    rc = daemon_spawn(command, stdinbuf, strlen(stdinbuf), stdoutbuf, sizeof(stdoutbuf));    if (rc >= 0 && stdoutbuf[0])      PrintOut(LOG_CRIT,"%s %s to %s produced unexpected output (%d bytes) to STDOUT/STDERR:\n%s\n",        newwarn, executable, newadd, strlen(stdoutbuf), stdoutbuf);    if (rc != 0)      PrintOut(LOG_CRIT,"%s %s to %s: failed, exit status %d\n",        newwarn, executable, newadd, rc);    else      PrintOut(LOG_INFO,"%s %s to %s: successful\n", newwarn, executable, newadd);  }#endif // _WIN32  // increment mail sent counter  mail->logged++;    // free copy of address (without commas)  address=FreeNonZero(address, -1, __LINE__, filenameandversion);  return;}// Printing function for watching ataprint commands, or losing them// [From GLIBC Manual: Since the prototype doesn't specify types for// optional arguments, in a call to a variadic function the default// argument promotions are performed on the optional argument// values. This means the objects of type char or short int (whether// signed or not) are promoted to either int or unsigned int, as// appropriate.]void pout(const char *fmt, ...){  va_list ap;  // get the correct time in syslog()  FixGlibcTimeZoneBug();  // initialize variable argument list   va_start(ap,fmt);  // in debug==1 mode we will print the output from the ataprint.o functions!  if (debugmode && debugmode!=2)#ifdef _WIN32   if (facility == LOG_LOCAL1) // logging to stdout    vfprintf(stderr,fmt,ap);   else   #endif    vprintf(fmt,ap);  // in debug==2 mode we print output from knowndrives.o functions  else if (debugmode==2 || con->reportataioctl || con->reportscsiioctl || con->controller_port) {    openlog("smartd", LOG_PID, facility);    vsyslog(LOG_INFO, fmt, ap);    closelog();  }  va_end(ap);  fflush(NULL);  return;}// This function prints either to stdout or to the syslog as needed.// This function is also used by utility.cpp to report LOG_CRIT errors.void PrintOut(int priority, const char *fmt, ...){  va_list ap;    // get the correct time in syslog()  FixGlibcTimeZoneBug();  // initialize variable argument list   va_start(ap,fmt);  if (debugmode) #ifdef _WIN32   if (facility == LOG_LOCAL1) // logging to stdout    vfprintf(stderr,fmt,ap);   else   #endif    vprintf(fmt,ap);  else {    openlog("smartd", LOG_PID, facility);    vsyslog(priority,fmt,ap);    closelog();  }  va_end(ap);  return;}// Wait for the pid file to show up, this makes sure a calling program knows// that the daemon is really up and running and has a pid to kill itbool WaitForPidFile(){    int waited, max_wait = 10;    struct stat stat_buf;    if(!pid_file || debugmode)    	return true;    for(waited = 0; waited < max_wait; ++waited) {	if(stat(pid_file, &stat_buf) == 0) {		return true;	} else		sleep(1);    }    return false;}// Forks new process, closes ALL file descriptors, redirects stdin,// stdout, and stderr.  Not quite daemon().  See// http://www.iar.unlp.edu.ar/~fede/revistas/lj/Magazines/LJ47/2335.html// for a good description of why we do things this way.void DaemonInit(){#ifndef _WIN32  pid_t pid;  int i;    // flush all buffered streams.  Else we might get two copies of open  // streams since both parent and child get copies of the buffers.  fflush(NULL);  if (do_fork) {    if ((pid=fork()) < 0) {      // unable to fork!      PrintOut(LOG_CRIT,"smartd unable to fork daemon process!\n");      EXIT(EXIT_STARTUP);    }    else if (pid)      // we are the parent process, wait for pid file, then exit cleanly      if(!WaitForPidFile()) {        PrintOut(LOG_CRIT,"PID file %s didn't show up!\n", pid_file);     	EXIT(EXIT_STARTUP);      } else        EXIT(0);      // from here on, we are the child process.    setsid();    // Fork one more time to avoid any possibility of having terminals    if ((pid=fork()) < 0) {      // unable to fork!      PrintOut(LOG_CRIT,"smartd unable to fork daemon process!\n");      EXIT(EXIT_STARTUP);    }    else if (pid)      // we are the parent process -- exit cleanly      EXIT(0);    // Now we are the child's child...  }  // close any open file descriptors  for (i=getdtablesize();i>=0;--i)    close(i);  #ifdef __CYGWIN__  // Cygwin's setsid() does not detach the process from Windows console  FreeConsole();#endif // __CYGWIN__  // redirect any IO attempts to /dev/null for stdin  i=open("/dev/null",O_RDWR);  // stdout  dup(i);  // stderr  dup(i);  umask(0);  chdir("/");  if (do_fork)    PrintOut(LOG_INFO, "smartd has fork()ed into background mode. New PID=%d.\n", (int)getpid());#else // _WIN32  // No fork() on native Win32  // Detach this process from console  fflush(NULL);  if (daemon_detach("smartd")) {    PrintOut(LOG_CRIT,"smartd unable to detach from console!\n");    EXIT(EXIT_STARTUP);  }  // stdin/out/err now closed if not redirected#endif // _WIN32  return;}// create a PID file containing the current process idvoid WritePidFile() {  if (pid_file) {    int error = 0;    pid_t pid = getpid();    mode_t old_umask;    FILE* fp; #ifndef __CYGWIN__    old_umask = umask(0077); // rwx------#else    // Cygwin: smartd service runs on system account, ensure PID file can be read by admins    old_umask = umask(0033); // rwxr--r--#endif    fp = fopen(pid_file, "w");    umask(old_umask);    if (fp == NULL) {      error = 1;    } else if (fprintf(fp, "%d\n", (int)pid) <= 0) {      error = 1;    } else if (fclose(fp) != 0) {      error = 1;    }    if (error) {      PrintOut(LOG_CRIT, "unable to write PID file %s - exiting.\n", pid_file);      EXIT(EXIT_PID);    }    PrintOut(LOG_INFO, "file %s written containing PID %d\n", pid_file, (int)pid);  }  return;}// Prints header identifying version of code and homevoid PrintHead(){#ifdef HAVE_GET_OS_VERSION_STR  const char * ver = get_os_version_str();#else  const char * ver = SMARTMONTOOLS_BUILD_HOST;#endif  PrintOut(LOG_INFO,"smartd version %s [%s] Copyright (C) 2002-8 Bruce Allen\n", PACKAGE_VERSION, ver);  PrintOut(LOG_INFO,"Home page is " PACKAGE_HOMEPAGE "\n\n");  return;}// prints help info for configuration file Directivesvoid Directives() {  PrintOut(LOG_INFO,           "Configuration file (%s) Directives (after device name):\n"           "  -d TYPE Set the device type: ata, scsi, marvell, removable, sat, 3ware,N, hpt,L/M/N, cciss,N\n"           "  -T TYPE Set the tolerance to one of: normal, permissive\n"           "  -o VAL  Enable/disable automatic offline tests (on/off)\n"           "  -S VAL  Enable/disable attribute autosave (on/off)\n"           "  -n MODE No check if: never[,q], sleep[,q], standby[,q], idle[,q]\n"           "  -H      Monitor SMART Health Status, report if failed\n"           "  -s REG  Do Self-Test at time(s) given by regular expression REG\n"           "  -l TYPE Monitor SMART log.  Type is one of: error, selftest\n"           "  -f      Monitor 'Usage' Attributes, report failures\n"           "  -m ADD  Send email warning to address ADD\n"           "  -M TYPE Modify email warning behavior (see man page)\n"           "  -p      Report changes in 'Prefailure' Attributes\n"           "  -u      Report changes in 'Usage' Attributes\n"           "  -t      Equivalent to -p and -u Directives\n"           "  -r ID   Also report Raw values of Attribute ID with -p, -u or -t\n"           "  -R ID   Track changes in Attribute ID Raw value with -p, -u or -t\n"           "  -i ID   Ignore Attribute ID for -f Directive\n"           "  -I ID   Ignore Attribute ID for -p, -u or -t Directive\n"	   "  -C ID   Monitor Current Pending Sectors in Attribute ID\n"	   "  -U ID   Monitor Offline Uncorrectable Sectors in Attribute ID\n"           "  -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"           "  -v N,ST Modifies labeling of Attribute N (see man page)  \n"           "  -P TYPE Drive-specific presets: use, ignore, show, showall\n"           "  -a      Default: -H -f -t -l error -l selftest -C 197 -U 198\n"           "  -F TYPE Firmware bug workaround: none, samsung, samsung2, samsung3\n"           "   #      Comment: text after a hash sign is ignored\n"           "   \\      Line continuation character\n"           "Attribute ID is a decimal integer 1 <= ID <= 255\n"

⌨️ 快捷键说明

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