// File: spjmurray[P]nagios-plugin-check-scsi-smart/check_scsi_smart.cc
// Function: main
int main(int argc, char** argv) {

  const char* device = 0;
  const char* warning = "";
  const char* critical = "";

  static struct option long_options[] = {
    { "help",     no_argument,       0, 'h' },
    { "version",  no_argument,       0, 'V' },
    { "device",   required_argument, 0, 'd' },
    { "warning",  required_argument, 0, 'w' },
    { "critical", required_argument, 0, 'c' },
    { 0,          0,                 0, 0   }
  };

  int c;
  while((c = getopt_long(argc, argv, "hVd:w:c:", long_options, 0)) != -1) {
    switch(c) {
      case 'h':
        help();
        exit(0);
      case 'V':
        version();
        exit(0);
      case 'd':
        device = optarg;
        break;
      case 'w':
        warning = optarg;
        break;
      case 'c':
        critical = optarg;
        break;
      default:
        usage();
        exit(1);
        break;
    }
  }

  // Check for required arguments
  if(!device) {
    help();
    exit(NAGIOS_UNKNOWN);
  }

  // Parse optional arguments
  SmartThresholdMap warning_thresholds;
  if(!parse_thresholds(warning_thresholds, warning)) {
    help();
    exit(NAGIOS_UNKNOWN);
  }

  SmartThresholdMap critical_thresholds;
  if(!parse_thresholds(critical_thresholds, critical)) {
    help();
    exit(NAGIOS_UNKNOWN);
  }

  // Check the device is compatible with the check
  int fd = open(device, O_RDWR);
  if(fd == -1) {
    cerr << "UNKNOWN: unable to open device " << device << endl;
    exit(NAGIOS_UNKNOWN);
  }

  int sg_version;
  if((ioctl(fd, SG_GET_VERSION_NUM, &sg_version) == -1) || sg_version < 30000) {
    cerr << "UNKNOWN: " << device << " is either not an sg device, or the driver is old" << endl;
    exit(NAGIOS_UNKNOWN);
  }

  // Check the device can use SMART and that it is enabled
  uint16_t identify[SECTOR_SIZE / 2];
  if(!ata_identify(fd, reinterpret_cast<unsigned char*>(identify))) {
    cout << "OK: ATA command set unsupported" << endl;
    exit(NAGIOS_OK);
  }

  if(~StorageEndian::swap(identify[82]) & 0x01) {
    cout << "OK: SMART feature set unsupported" << endl;
    exit(NAGIOS_OK);
  }

  if(~StorageEndian::swap(identify[85]) & 0x01) {
    cout << "UNKNOWN: SMART feature set disabled" << endl;
    exit(NAGIOS_UNKNOWN);
  }

  int code = NAGIOS_OK;
  int prdfail = 0;
  int advisory = 0;
  int crit = 0;
  int warn = 0;
  int logs = 0;
  stringstream perfdata;

  // Perform the checks
  check_smart_attributes(fd, critical_thresholds, warning_thresholds, code, prdfail, advisory, crit, warn, perfdata);
  check_smart_log(fd, code, logs);

  // Print out the results and performance data
  const char* status[] = { "OK", "WARNING", "CRITICAL" };
  cout << status[code]
       << ": prdfail " << prdfail
       << ", advisory " << advisory
       << ", critical " << crit
       << ", warning " << warn
       << ", logs " << logs
       << " |" << perfdata.str()
       << endl;

  close(fd);

  return code;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x5f0, %rsp            # imm = 0x5F0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
leaq 0x3f47(%rip), %rax      # 0x92df
movq %rax, -0x20(%rbp)
leaq 0x3f3c(%rip), %rax      # 0x92df
movq %rax, -0x28(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x3ef8(%rip), %rdx      # 0x92ad
leaq 0x7e54(%rip), %rcx      # 0xd210
xorl %eax, %eax
movl %eax, %r8d
callq 0x4340
movl %eax, -0x2c(%rbp)
cmpl $-0x1, %eax
je 0x5459
movl -0x2c(%rbp), %eax
addl $-0x56, %eax
movl %eax, %ecx
movq %rcx, -0x4e8(%rbp)
subl $0x21, %eax
ja 0x5445
movq -0x4e8(%rbp), %rax
leaq 0x3c10(%rip), %rcx      # 0x9004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
callq 0x4620
xorl %edi, %edi
callq 0x4290
callq 0x4570
xorl %edi, %edi
callq 0x4290
movq 0x7b9c(%rip), %rax      # 0xcfb8
movq (%rax), %rax
movq %rax, -0x18(%rbp)
jmp 0x5454
movq 0x7b8c(%rip), %rax      # 0xcfb8
movq (%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0x5454
movq 0x7b7c(%rip), %rax      # 0xcfb8
movq (%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x5454
callq 0x45c0
movl $0x1, %edi
callq 0x4290
jmp 0x53a7
cmpq $0x0, -0x18(%rbp)
jne 0x546f
callq 0x4620
movl $0x3, %edi
callq 0x4290
leaq -0x60(%rbp), %rdi
callq 0x5fb0
movq -0x20(%rbp), %rax
movq %rax, -0x4f8(%rbp)
leaq -0x81(%rbp), %rdi
movq %rdi, -0x4f0(%rbp)
callq 0x4390
movq -0x4f8(%rbp), %rsi
movq -0x4f0(%rbp), %rdx
leaq -0x80(%rbp), %rdi
callq 0x5fd0
jmp 0x54af
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x4fd0
movb %al, -0x4f9(%rbp)
jmp 0x54c4
movb -0x4f9(%rbp), %al
xorb $-0x1, %al
movb %al, -0x4fa(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x4130
leaq -0x81(%rbp), %rdi
callq 0x4260
movb -0x4fa(%rbp), %al
testb $0x1, %al
jne 0x54f3
jmp 0x555b
callq 0x4620
jmp 0x54fa
movl $0x3, %edi
callq 0x4290
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5533
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x4130
leaq -0x81(%rbp), %rdi
callq 0x4260
jmp 0x5b9c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5b9c
leaq -0xc8(%rbp), %rdi
callq 0x5fb0
movq -0x28(%rbp), %rax
movq %rax, -0x510(%rbp)
leaq -0xe9(%rbp), %rdi
movq %rdi, -0x508(%rbp)
callq 0x4390
movq -0x510(%rbp), %rsi
movq -0x508(%rbp), %rdx
leaq -0xe8(%rbp), %rdi
callq 0x5fd0
jmp 0x55a1
leaq -0xc8(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x4fd0
movb %al, -0x511(%rbp)
jmp 0x55bc
movb -0x511(%rbp), %al
xorb $-0x1, %al
movb %al, -0x512(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x4130
leaq -0xe9(%rbp), %rdi
callq 0x4260
movb -0x512(%rbp), %al
testb $0x1, %al
jne 0x55ee
jmp 0x5659
callq 0x4620
jmp 0x55f5
movl $0x3, %edi
callq 0x4290
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5631
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x4130
leaq -0xe9(%rbp), %rdi
callq 0x4260
jmp 0x5b90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5b90
movq -0x18(%rbp), %rdi
xorl %eax, %eax
movl $0x2, %esi
callq 0x4180
movl %eax, -0x518(%rbp)
jmp 0x5671
movl -0x518(%rbp), %eax
movl %eax, -0xf0(%rbp)
cmpl $-0x1, -0xf0(%rbp)
jne 0x56da
movq 0x795b(%rip), %rdi      # 0xcfe8
leaq 0x3c22(%rip), %rsi      # 0x92b6
callq 0x4200
movq %rax, -0x520(%rbp)
jmp 0x56a2
movq -0x520(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x4200
movq %rax, -0x528(%rbp)
jmp 0x56bb
movq -0x528(%rbp), %rdi
movq 0x78e7(%rip), %rsi      # 0xcfb0
callq 0x4240
jmp 0x56d0
movl $0x3, %edi
callq 0x4290
movl -0xf0(%rbp), %edi
movl $0x2282, %esi           # imm = 0x2282
leaq -0xf4(%rbp), %rdx
movb $0x0, %al
callq 0x4300
cmpl $-0x1, %eax
je 0x5704
cmpl $0x7530, -0xf4(%rbp)    # imm = 0x7530
jge 0x5774
movq 0x78dd(%rip), %rdi      # 0xcfe8
leaq 0x3bc4(%rip), %rsi      # 0x92d6
callq 0x4200
movq %rax, -0x530(%rbp)
jmp 0x5720
movq -0x530(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x4200
movq %rax, -0x538(%rbp)
jmp 0x5739
movq -0x538(%rbp), %rdi
leaq 0x3b99(%rip), %rsi      # 0x92e0
callq 0x4200
movq %rax, -0x540(%rbp)
jmp 0x5755
movq -0x540(%rbp), %rdi
movq 0x784d(%rip), %rsi      # 0xcfb0
callq 0x4240
jmp 0x576a
movl $0x3, %edi
callq 0x4290
movl -0xf0(%rbp), %edi
leaq -0x300(%rbp), %rsi
callq 0x4890
movb %al, -0x541(%rbp)
jmp 0x578e
movb -0x541(%rbp), %al
testb $0x1, %al
jne 0x57d2
jmp 0x579a
movq 0x7827(%rip), %rdi      # 0xcfc8
leaq 0x3b6a(%rip), %rsi      # 0x9312
callq 0x4200
movq %rax, -0x550(%rbp)
jmp 0x57b6
movq -0x550(%rbp), %rdi
movq 0x77ec(%rip), %rsi      # 0xcfb0
callq 0x4240
jmp 0x57cb
xorl %edi, %edi
callq 0x4290
movzwl -0x25c(%rbp), %edi
callq 0x5d90
movw %ax, -0x552(%rbp)
jmp 0x57e7
movw -0x552(%rbp), %ax
movzwl %ax, %eax
xorl $-0x1, %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x5834
movq 0x77c5(%rip), %rdi      # 0xcfc8
leaq 0x3b28(%rip), %rsi      # 0x9332
callq 0x4200
movq %rax, -0x560(%rbp)
jmp 0x5818
movq -0x560(%rbp), %rdi
movq 0x778a(%rip), %rsi      # 0xcfb0
callq 0x4240
jmp 0x582d
xorl %edi, %edi
callq 0x4290
movzwl -0x256(%rbp), %edi
callq 0x5d90
movw %ax, -0x562(%rbp)
jmp 0x5849
movw -0x562(%rbp), %ax
movzwl %ax, %eax
xorl $-0x1, %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x5899
movq 0x7763(%rip), %rdi      # 0xcfc8
leaq 0x3ae8(%rip), %rsi      # 0x9354
callq 0x4200
movq %rax, -0x570(%rbp)
jmp 0x587a
movq -0x570(%rbp), %rdi
movq 0x7728(%rip), %rsi      # 0xcfb0
callq 0x4240
jmp 0x588f
movl $0x3, %edi
callq 0x4290
movl $0x0, -0x304(%rbp)
movl $0x0, -0x308(%rbp)
movl $0x0, -0x30c(%rbp)
movl $0x0, -0x310(%rbp)
movl $0x0, -0x314(%rbp)
movl $0x0, -0x318(%rbp)
leaq -0x4a0(%rbp), %rdi
callq 0x4160
jmp 0x58e3
movl -0xf0(%rbp), %edi
leaq -0x490(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x10(%rax)
leaq -0x314(%rbp), %rcx
movq %rcx, 0x8(%rax)
leaq -0x310(%rbp), %rcx
movq %rcx, (%rax)
leaq -0xc8(%rbp), %rsi
leaq -0x60(%rbp), %rdx
leaq -0x304(%rbp), %rcx
leaq -0x308(%rbp), %r8
leaq -0x30c(%rbp), %r9
callq 0x4b90
jmp 0x5933
movl -0xf0(%rbp), %edi
leaq -0x304(%rbp), %rsi
leaq -0x318(%rbp), %rdx
callq 0x4e70
jmp 0x594e
movq 0x743b(%rip), %rax      # 0xcd90
movq %rax, -0x4b0(%rbp)
movaps 0x741d(%rip), %xmm0     # 0xcd80
movaps %xmm0, -0x4c0(%rbp)
movslq -0x304(%rbp), %rax
movq -0x4c0(%rbp,%rax,8), %rsi
movq 0x7648(%rip), %rdi      # 0xcfc8
callq 0x4200
movq %rax, -0x578(%rbp)
jmp 0x598e
movq -0x578(%rbp), %rdi
leaq 0x39f0(%rip), %rsi      # 0x938c
callq 0x4200
movq %rax, -0x580(%rbp)
jmp 0x59aa
movq -0x580(%rbp), %rdi
movl -0x308(%rbp), %esi
callq 0x4370
movq %rax, -0x588(%rbp)
jmp 0x59c5
movq -0x588(%rbp), %rdi
leaq 0x39c4(%rip), %rsi      # 0x9397
callq 0x4200
movq %rax, -0x590(%rbp)
jmp 0x59e1
movq -0x590(%rbp), %rdi
movl -0x30c(%rbp), %esi
callq 0x4370
movq %rax, -0x598(%rbp)
jmp 0x59fc
movq -0x598(%rbp), %rdi
leaq 0x3999(%rip), %rsi      # 0x93a3
callq 0x4200
movq %rax, -0x5a0(%rbp)
jmp 0x5a18
movq -0x5a0(%rbp), %rdi
movl -0x310(%rbp), %esi
callq 0x4370
movq %rax, -0x5a8(%rbp)
jmp 0x5a33
movq -0x5a8(%rbp), %rdi
leaq 0x396e(%rip), %rsi      # 0x93af
callq 0x4200
movq %rax, -0x5b0(%rbp)
jmp 0x5a4f
movq -0x5b0(%rbp), %rdi
movl -0x314(%rbp), %esi
callq 0x4370
movq %rax, -0x5b8(%rbp)
jmp 0x5a6a
movq -0x5b8(%rbp), %rdi
leaq 0x3942(%rip), %rsi      # 0x93ba
callq 0x4200
movq %rax, -0x5c0(%rbp)
jmp 0x5a86
movq -0x5c0(%rbp), %rdi
movl -0x318(%rbp), %esi
callq 0x4370
movq %rax, -0x5c8(%rbp)
jmp 0x5aa1
movq -0x5c8(%rbp), %rdi
leaq 0x3913(%rip), %rsi      # 0x93c2
callq 0x4200
movq %rax, -0x5d0(%rbp)
jmp 0x5abd
leaq -0x4e0(%rbp), %rdi
leaq -0x4a0(%rbp), %rsi
callq 0x41f0
jmp 0x5ad2
movq -0x5d0(%rbp), %rdi
leaq -0x4e0(%rbp), %rsi
callq 0x41e0
movq %rax, -0x5d8(%rbp)
jmp 0x5aee
movq -0x5d8(%rbp), %rdi
movq 0x74b4(%rip), %rsi      # 0xcfb0
callq 0x4240
jmp 0x5b03
leaq -0x4e0(%rbp), %rdi
callq 0x4130
movl -0xf0(%rbp), %edi
callq 0x43d0
jmp 0x5b1c
movl -0x304(%rbp), %eax
movl %eax, -0x4(%rbp)
leaq -0x4a0(%rbp), %rdi
callq 0x4190
leaq -0xc8(%rbp), %rdi
callq 0x6080
leaq -0x60(%rbp), %rdi
callq 0x6080
movl -0x4(%rbp), %eax
addq $0x5f0, %rsp            # imm = 0x5F0
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5b84
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x4e0(%rbp), %rdi
callq 0x4130
leaq -0x4a0(%rbp), %rdi
callq 0x4190
leaq -0xc8(%rbp), %rdi
callq 0x6080
leaq -0x60(%rbp), %rdi
callq 0x6080
movq -0x90(%rbp), %rdi
callq 0x4380
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)