#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
struct passwd {
  char *pw_passwd;
  scalar_t__ pw_gid;
  int /*<<< orphan*/ pw_uid;
};

/* Variables and functions */
int /*<<< orphan*/ die(char *);
int /*<<< orphan*/ endpwent();
scalar_t__ getegid();
scalar_t__ geteuid();
struct passwd *getpwuid(int /*<<< orphan*/);
int /*<<< orphan*/ getuid();
scalar_t__ setgid(scalar_t__);
scalar_t__ setuid(int /*<<< orphan*/);
const char *getpw(void) {
  const char *rval;
  struct passwd *pw;
  pw = getpwuid(getuid());
  if (!pw)
    die("slock: cannot retrieve password entry (make sure to suid or sgid "
        "slock)\n");
  endpwent();
  rval = pw->pw_passwd;
  if (geteuid() == 0 && ((getegid() != pw->pw_gid && setgid(pw->pw_gid) < 0) ||
                         setuid(pw->pw_uid) < 0))
    die("slock: cannot drop privileges\n");
  return rval;
}


x86 assembly (clang, -O0):
<getpw>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    $0x0,%al
call   1040 <getuid@plt>
mov    %eax,%edi
call   1030 <getpwuid@plt>
mov    %rax,-0x10(%rbp)
cmpq   $0x0,-0x10(%rbp)
jne    11b1 <getpw+0x31>
lea    0xe54(%rip),%rdi
call   1090 <die@plt>
mov    $0x0,%al
call   1060 <endpwent@plt>
mov    -0x10(%rbp),%rax
mov    (%rax),%rax
mov    %rax,-0x8(%rbp)
mov    $0x0,%al
call   1050 <geteuid@plt>
cmp    $0x0,%rax
jne    1222 <getpw+0xa2>
mov    $0x0,%al
call   1070 <getegid@plt>
mov    -0x10(%rbp),%rcx
cmp    0x8(%rcx),%rax
je     1200 <getpw+0x80>
mov    -0x10(%rbp),%rax
mov    0x8(%rax),%rdi
call   1080 <setgid@plt>
cmp    $0x0,%rax
jl     1216 <getpw+0x96>
mov    -0x10(%rbp),%rax
mov    0x10(%rax),%edi
call   10a0 <setuid@plt>
cmp    $0x0,%rax
jge    1222 <getpw+0xa2>
lea    0xe2c(%rip),%rdi
call   1090 <die@plt>
mov    -0x8(%rbp),%rax
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<getpw>:
push   %r14
push   %rbx
push   %rax
xor    %eax,%eax
call   1040 <getuid@plt>
mov    %eax,%edi
call   1030 <getpwuid@plt>
mov    %rax,%rbx
test   %rax,%rax
jne    11a6 <getpw+0x26>
lea    0xe5f(%rip),%rdi
call   1090 <die@plt>
xor    %eax,%eax
call   1060 <endpwent@plt>
mov    (%rbx),%r14
xor    %eax,%eax
call   1050 <geteuid@plt>
test   %rax,%rax
jne    11ef <getpw+0x6f>
xor    %eax,%eax
call   1070 <getegid@plt>
mov    0x8(%rbx),%rdi
cmp    %rdi,%rax
je     11d6 <getpw+0x56>
call   1080 <setgid@plt>
test   %rax,%rax
js     11e3 <getpw+0x63>
mov    0x10(%rbx),%edi
call   10a0 <setuid@plt>
test   %rax,%rax
jns    11ef <getpw+0x6f>
lea    0xe5f(%rip),%rdi
call   1090 <die@plt>
mov    %r14,%rax
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
%struct.passwd = type { i8*, i64, i32 }
@.str = [73 x i8] c"slock: cannot retrieve password entry (make sure to suid or sgid slock)\0A\00"
@.str.1 = [31 x i8] c"slock: cannot drop privileges\0A\00"
define i8* @getpw() {
%1 = alloca i8*
%2 = alloca %struct.passwd*
%3 = call i32 (...) @getuid()
%4 = call %struct.passwd* @getpwuid(i32 %3)
store %struct.passwd* %4, %struct.passwd** %2
%5 = load %struct.passwd*, %struct.passwd** %2
%6 = icmp ne %struct.passwd* %5, null
br i1 %6, label %9, label %7
7: ; preds = %0
%8 = call i32 @die(i8* getelementptr inbounds ([73 x i8], [73 x i8]* @.str, i64 0, i64 0))
br label %9
9: ; preds = %7, %0
%10 = call i32 (...) @endpwent()
%11 = load %struct.passwd*, %struct.passwd** %2
%12 = getelementptr inbounds %struct.passwd, %struct.passwd* %11, i32 0, i32 0
%13 = load i8*, i8** %12
store i8* %13, i8** %1
%14 = call i64 (...) @geteuid()
%15 = icmp eq i64 %14, 0
br i1 %15, label %16, label %36
16: ; preds = %9
%17 = call i64 (...) @getegid()
%18 = load %struct.passwd*, %struct.passwd** %2
%19 = getelementptr inbounds %struct.passwd, %struct.passwd* %18, i32 0, i32 1
%20 = load i64, i64* %19
%21 = icmp ne i64 %17, %20
br i1 %21, label %22, label %28
22: ; preds = %16
%23 = load %struct.passwd*, %struct.passwd** %2
%24 = getelementptr inbounds %struct.passwd, %struct.passwd* %23, i32 0, i32 1
%25 = load i64, i64* %24
%26 = call i64 @setgid(i64 %25)
%27 = icmp slt i64 %26, 0
br i1 %27, label %34, label %28
28: ; preds = %22, %16
%29 = load %struct.passwd*, %struct.passwd** %2
%30 = getelementptr inbounds %struct.passwd, %struct.passwd* %29, i32 0, i32 2
%31 = load i32, i32* %30
%32 = call i64 @setuid(i32 %31)
%33 = icmp slt i64 %32, 0
br i1 %33, label %34, label %36
34: ; preds = %28, %22
%35 = call i32 @die(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.1, i64 0, i64 0))
br label %36
36: ; preds = %34, %28, %9
%37 = load i8*, i8** %1
ret i8* %37
}

LLVM IR (-O2):
%struct.passwd = type { i8*, i64, i32 }
@.str = [73 x i8] c"slock: cannot retrieve password entry (make sure to suid or sgid slock)\0A\00"
@.str.1 = [31 x i8] c"slock: cannot drop privileges\0A\00"
define i8* @getpw() {
%1 = tail call i32 (...) @getuid()
%2 = tail call %struct.passwd* @getpwuid(i32 %1)
%3 = icmp eq %struct.passwd* %2, null
br i1 %3, label %4, label %6
4: ; preds = %0
%5 = tail call i32 @die(i8* getelementptr inbounds ([73 x i8], [73 x i8]* @.str, i64 0, i64 0))
br label %6
6: ; preds = %4, %0
%7 = tail call i32 (...) @endpwent()
%8 = getelementptr inbounds %struct.passwd, %struct.passwd* %2, i64 0, i32 0
%9 = load i8*, i8** %8
%10 = tail call i64 (...) @geteuid()
%11 = icmp eq i64 %10, 0
br i1 %11, label %12, label %27
12: ; preds = %6
%13 = tail call i64 (...) @getegid()
%14 = getelementptr inbounds %struct.passwd, %struct.passwd* %2, i64 0, i32 1
%15 = load i64, i64* %14
%16 = icmp eq i64 %13, %15
br i1 %16, label %20, label %17
17: ; preds = %12
%18 = tail call i64 @setgid(i64 %15)
%19 = icmp slt i64 %18, 0
br i1 %19, label %25, label %20
20: ; preds = %17, %12
%21 = getelementptr inbounds %struct.passwd, %struct.passwd* %2, i64 0, i32 2
%22 = load i32, i32* %21
%23 = tail call i64 @setuid(i32 %22)
%24 = icmp slt i64 %23, 0
br i1 %24, label %25, label %27
25: ; preds = %20, %17
%26 = tail call i32 @die(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.1, i64 0, i64 0))
br label %27
27: ; preds = %25, %20, %6
ret i8* %9
}