static void
add_abrt (CcPrivacyPanel *self)
{
  GtkWidget *w;
  GtkWidget *dialog;
  char *os_name, *url, *msg;

  w = get_abrt_label (self->priv->privacy_settings, REPORT_TECHNICAL_PROBLEMS);
  self->priv->abrt_row = add_row (self, _("Problem Reporting"), "abrt_dialog", w);
  gtk_widget_hide (self->priv->abrt_row);

  dialog = self->priv->abrt_dialog;
  g_signal_connect (dialog, "delete-event",
                    G_CALLBACK (gtk_widget_hide_on_delete), NULL);

  w = GTK_WIDGET (gtk_builder_get_object (self->priv->builder, "abrt_switch"));
  g_settings_bind (self->priv->privacy_settings, REPORT_TECHNICAL_PROBLEMS,
                   w, "active",
                   G_SETTINGS_BIND_DEFAULT);

  os_name = get_os_name ();
  /* translators: '%s' is the distributor's name, such as 'Fedora' */
  msg = g_strdup_printf (_("Sending reports of technical problems helps us improve %s. Reports are sent anonymously and are scrubbed of personal data."),
                         os_name);
  g_free (os_name);
  gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (self->priv->builder, "abrt_explanation_label")), msg);
  g_free (msg);

  url = get_privacy_policy_url ();
  if (!url)
    {
      g_debug ("Not watching for ABRT appearing, /etc/os-release lacks a privacy policy URL");
      return;
    }
  msg = g_strdup_printf ("<a href=\"%s\">%s</a>", url, _("Privacy Policy"));
  g_free (url);
  gtk_label_set_markup (GTK_LABEL (gtk_builder_get_object (self->priv->builder, "abrt_policy_linklabel")), msg);
  g_free (msg);

  self->priv->abrt_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
                                                "org.freedesktop.problems.daemon",
                                                G_BUS_NAME_WATCHER_FLAGS_NONE,
                                                abrt_appeared_cb,
                                                abrt_vanished_cb,
                                                self,
                                                NULL);
}
예제 #2
0
파일: gzip.c 프로젝트: jsummers/deark
static int do_gzip_read_member(deark *c, lctx *d, i64 pos1, i64 *member_size)
{
	u8 b0, b1;
	i64 pos;
	i64 n;
	i64 foundpos;
	i64 string_len;
	i64 cmpr_data_len;
	i64 mod_time_unix;
	u32 crc_calculated;
	de_ucstring *member_name = NULL;
	int saved_indent_level;
	int ret;
	struct member_data *md = NULL;
	int retval = 0;

	md = de_malloc(c, sizeof(struct member_data));

	de_dbg_indent_save(c, &saved_indent_level);

	de_dbg(c, "gzip member at %d", (int)pos1);
	de_dbg_indent(c, 1);
	pos = pos1;

	b0 = de_getbyte(pos+0);
	b1 = de_getbyte(pos+1);
	if(b0!=0x1f || b1!=0x8b) {
		de_err(c, "Invalid gzip signature at %d. This is not a valid gzip file.",
			(int)pos1);
		goto done;
	}

	md->cmpr_code = de_getbyte(pos+2);
	if(md->cmpr_code!=0x08) {
		de_err(c, "Unsupported compression type (%d)", (int)md->cmpr_code);
		goto done;
	}

	md->flags = de_getbyte(pos+3);
	de_dbg(c, "flags: 0x%02x", (unsigned int)md->flags);
	pos += 4;

	mod_time_unix = de_getu32le(pos);
	de_unix_time_to_timestamp(mod_time_unix, &md->mod_time_ts, 0x1);
	if(md->mod_time_ts.is_valid) {
		char timestamp_buf[64];
		de_timestamp_to_string(&md->mod_time_ts, timestamp_buf, sizeof(timestamp_buf), 0);
		de_dbg(c, "mod time: %" I64_FMT " (%s)", mod_time_unix, timestamp_buf);
	}
	pos += 4;

	b0 = de_getbyte(pos++);
	de_dbg(c, "extra flags: 0x%02x", (unsigned int)b0);

	b0 = de_getbyte(pos++);
	de_dbg(c, "OS or filesystem: %d (%s)", (int)b0, get_os_name(b0));

	if(md->flags & GZIPFLAG_FEXTRA) {
		n = de_getu16le(pos); // XLEN
		// TODO: It might be interesting to dissect these extra fields, but it's
		// hard to find even a single file that uses them.
		de_dbg(c, "[extra fields at %d, dpos=%d, dlen=%d]",
			(int)pos, (int)(pos+2), (int)n);
		pos += 2;
		pos += n;
	}

	if(md->flags & GZIPFLAG_FNAME) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid NAME field");
			goto done;
		}

		string_len = foundpos - pos;

		member_name = ucstring_create(c);
#define DE_GZIP_MAX_FNLEN 300
		dbuf_read_to_ucstring_n(c->infile, pos, string_len, DE_GZIP_MAX_FNLEN,
			member_name, 0, DE_ENCODING_LATIN1);
		de_dbg(c, "file name at %d, len=%d: \"%s\"", (int)pos, (int)string_len,
			ucstring_getpsz_d(member_name));
		pos = foundpos + 1;
	}

	if(md->flags & GZIPFLAG_FCOMMENT) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid COMMENT field");
			goto done;
		}
		pos = foundpos + 1;
	}

	if(md->flags & GZIPFLAG_FHCRC) {
		md->crc16_reported = (u32)de_getu16le(pos);
		de_dbg(c, "crc16 (reported): 0x%04x", (unsigned int)md->crc16_reported);
		pos += 2;
	}

	de_dbg(c, "compressed blocks at %d", (int)pos);

	if(!d->output_file) {
		// Although any member can have a name and mod time, this metadata
		// is ignored for members after the first one.
		de_finfo *fi = NULL;

		fi = de_finfo_create(c);

		if(member_name && c->filenames_from_file) {
			de_finfo_set_name_from_ucstring(c, fi, member_name, 0);
			fi->original_filename_flag = 1;
		}

		if(md->mod_time_ts.is_valid) {
			fi->mod_time = md->mod_time_ts;
		}

		d->output_file = dbuf_create_output_file(c, member_name?NULL:"bin", fi, 0);

		de_finfo_destroy(c, fi);
	}

	d->output_file->writecallback_fn = our_writecallback;
	d->output_file->userdata = (void*)md;
	md->crco = d->crco;
	de_crcobj_reset(md->crco);

	ret = de_decompress_deflate(c->infile, pos, c->infile->len - pos, d->output_file,
		0, &cmpr_data_len, 0);

	crc_calculated = de_crcobj_getval(md->crco);
	d->output_file->writecallback_fn = NULL;
	d->output_file->userdata = NULL;

	if(!ret) goto done;
	pos += cmpr_data_len;

	de_dbg(c, "crc32 (calculated): 0x%08x", (unsigned int)crc_calculated);

	md->crc32_reported = (u32)de_getu32le(pos);
	de_dbg(c, "crc32 (reported)  : 0x%08x", (unsigned int)md->crc32_reported);
	pos += 4;

	if(crc_calculated != md->crc32_reported) {
		de_warn(c, "CRC check failed: Expected 0x%08x, got 0x%08x",
			(unsigned int)md->crc32_reported, (unsigned int)crc_calculated);
	}

	md->isize = de_getu32le(pos);
	de_dbg(c, "uncompressed size (mod 2^32): %u", (unsigned int)md->isize);
	pos += 4;

	retval = 1;

done:
	if(retval)
		*member_size = pos - pos1;
	else
		*member_size = 0;
	ucstring_destroy(member_name);
	de_free(c, md);
	de_dbg_indent_restore(c, saved_indent_level);
	return retval;
}
예제 #3
0
static int do_gzip_read_member(deark *c, lctx *d, de_int64 pos1, de_int64 *member_size)
{
	de_byte b0, b1;
	de_int64 cmpr_code;
	de_int64 pos;
	de_int64 n;
	de_int64 foundpos;
	de_int64 string_len;
	de_int64 cmpr_data_len;
	de_int64 isize;
	de_int64 mod_time_unix;
	struct de_timestamp mod_time_ts;
	de_uint32 crc32_field;
	de_ucstring *member_name = NULL;
	de_finfo *fi = NULL;
	int saved_indent_level;
	int ret;
	int retval = 0;

	mod_time_ts.is_valid = 0;

	de_dbg_indent_save(c, &saved_indent_level);

	de_dbg(c, "gzip member at %d\n", (int)pos1);
	de_dbg_indent(c, 1);
	pos = pos1;

	b0 = de_getbyte(pos+0);
	b1 = de_getbyte(pos+1);
	if(b0!=0x1f || b1!=0x8b) {
		de_err(c, "Invalid gzip signature at %d. This is not a valid gzip file.\n",
			(int)pos1);
		goto done;
	}

	cmpr_code=de_getbyte(pos+2);
	if(cmpr_code!=0x08) {
		de_err(c, "Unsupported compression type (%d)\n", (int)cmpr_code);
		goto done;
	}

	d->flags = de_getbyte(pos+3);
	de_dbg(c, "flags: 0x%02x\n", (unsigned int)d->flags);
	pos += 4;

	mod_time_unix = de_getui32le(pos);
	de_unix_time_to_timestamp(mod_time_unix, &mod_time_ts);
	if(mod_time_ts.is_valid) {
		char timestamp_buf[64];
		de_timestamp_to_string(&mod_time_ts, timestamp_buf, sizeof(timestamp_buf), 1);
		de_dbg(c, "mod time: %" INT64_FMT " (%s)\n", mod_time_unix, timestamp_buf);
	}
	pos += 4;

	b0 = de_getbyte(pos++);
	de_dbg(c, "extra flags: 0x%02x\n", (unsigned int)b0);

	b0 = de_getbyte(pos++);
	de_dbg(c, "OS or filesystem: %d (%s)\n", (int)b0, get_os_name(b0));

	if(d->flags & GZIPFLAG_FEXTRA) {
		n = de_getui16le(pos); // XLEN
		// TODO: It might be interesting to dissect these extra fields, but it's
		// hard to find even a single file that uses them.
		de_dbg(c, "[extra fields at %d, dpos=%d, dlen=%d]\n",
			(int)pos, (int)(pos+2), (int)n);
		pos += 2;
		pos += n;
	}

	if(d->flags & GZIPFLAG_FNAME) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid NAME field\n");
			goto done;
		}

		string_len = foundpos - pos;

		member_name = ucstring_create(c);
		dbuf_read_to_ucstring_n(c->infile, pos, string_len, 300, member_name, 0, DE_ENCODING_LATIN1);
		de_dbg(c, "file name at %d, len=%d: \"%s\"\n", (int)pos, (int)string_len,
			ucstring_get_printable_sz(member_name));
		pos = foundpos + 1;
	}

	if(d->flags & GZIPFLAG_FCOMMENT) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid COMMENT field\n");
			goto done;
		}
		pos = foundpos + 1;
	}

	if(d->flags & GZIPFLAG_FHCRC) {
		pos += 2;
	}

	de_dbg(c, "compressed blocks at %d\n", (int)pos);

	if(!d->output_file) {
		fi = de_finfo_create(c);

		if(member_name && c->filenames_from_file) {
			de_finfo_set_name_from_ucstring(c, fi, member_name);
			fi->original_filename_flag = 1;
		}

		if(mod_time_ts.is_valid) {
			fi->mod_time = mod_time_ts;
		}

		d->output_file = dbuf_create_output_file(c, member_name?NULL:"bin", fi, 0);
	}

	ret = de_uncompress_deflate(c->infile, pos, c->infile->len - pos, d->output_file, &cmpr_data_len);

	if(!ret) goto done;
	pos += cmpr_data_len;

	crc32_field = (de_uint32)de_getui32le(pos);
	de_dbg(c, "crc32: 0x%08x\n", (unsigned int)crc32_field);
	pos += 4;
	// TODO: Validate CRCs

	isize = de_getui32le(pos);
	de_dbg(c, "uncompressed size (mod 2^32): %u\n", (unsigned int)isize);
	pos += 4;

	retval = 1;

done:
	if(retval)
		*member_size = pos - pos1;
	else
		*member_size = 0;
	ucstring_destroy(member_name);
	de_finfo_destroy(c, fi);
	de_dbg_indent_restore(c, saved_indent_level);
	return retval;
}
예제 #4
0
sg_host_info *sg_get_host_info()
{
    static sg_host_info general_stat;
#ifndef WIN32
    static struct utsname os;
#endif

#ifdef HPUX
    struct pst_static *pstat_static;
    time_t currtime;
    long boottime;
#endif
#ifdef SOLARIS
    time_t boottime,curtime;
    kstat_ctl_t *kc;
    kstat_t *ksp;
    kstat_named_t *kn;
#endif
#if defined(LINUX) || defined(CYGWIN)
    FILE *f;
#endif
#ifdef ALLBSD
    int mib[2];
    struct timeval boottime;
    time_t curtime;
    size_t size;
#endif
#ifdef WIN32
    unsigned long nameln;
    char *name;
    long long result;
    OSVERSIONINFOEX osinfo;
    SYSTEM_INFO sysinfo;
    char *tmp_name;
    char tmp[10];
#endif

#ifndef WIN32 /* Trust windows to be different */
    if((uname(&os)) < 0) {
        sg_set_error_with_errno(SG_ERROR_UNAME, NULL);
        return NULL;
    }

    general_stat.os_name = os.sysname;
    general_stat.os_release = os.release;
    general_stat.os_version = os.version;
    general_stat.platform = os.machine;
    general_stat.hostname = os.nodename;
#else /* WIN32 */
    if (!runonce) {
        /* these settings are static after boot, so why get them
         * constantly? */

        /* get system name */
        nameln = MAX_COMPUTERNAME_LENGTH + 1;
        name = sg_malloc(nameln);
        if(name == NULL) {
            return NULL;
        }
        if(GetComputerName(name, &nameln) == 0) {
            free(name);
            sg_set_error(SG_ERROR_HOST, "GetComputerName");
            return NULL;
        }
        if(sg_update_string(&general_stat.hostname, name)) {
            free(name);
            return NULL;
        }
        free(name);

        /* get OS name, version and build */
        ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX));
        osinfo.dwOSVersionInfoSize = sizeof(osinfo);
        if(!GetVersionEx(&osinfo)) {
            sg_set_error(SG_ERROR_HOST, "GetVersionEx");
            return NULL;
        }

        /* Release - single number */
        if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) {
            free(tmp);
            return NULL;
        }
        if(sg_update_string(&general_stat.os_release, tmp)) {
            free(tmp);
            return NULL;
        }

        /* Version */
        /* usually a single digit . single digit, eg 5.0 */
        if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion,
                    osinfo.dwMinorVersion) == -1) {
            free(tmp);
            return NULL;
        }
        if(sg_update_string(&general_stat.os_version, tmp)) {
            free(tmp);
            return NULL;
        }

        /* OS name */
        tmp_name = get_os_name(osinfo);
        if(tmp_name == NULL) {
            return NULL;
        }
        if(sg_update_string(&general_stat.os_name, tmp_name)) {
            free(tmp_name);
            return NULL;
        }
        free(tmp_name);
        runonce = 1;

        /* Platform */
        GetSystemInfo(&sysinfo);
        switch(sysinfo.wProcessorArchitecture) {
        case PROCESSOR_ARCHITECTURE_INTEL:
            if(sg_update_string(&general_stat.platform,
                                "Intel")) {
                return NULL;
            }
            break;
        case PROCESSOR_ARCHITECTURE_IA64:
            if(sg_update_string(&general_stat.platform,
                                "IA64")) {
                return NULL;
            }
            break;
        case PROCESSOR_ARCHITECTURE_AMD64:
            if(sg_update_string(&general_stat.platform,
                                "AMD64")) {
                return NULL;
            }
            break;
        default:
            if(sg_update_string(&general_stat.platform,
                                "Unknown")) {
                return NULL;
            }
            break;
        }
    }
#endif /* WIN32 */

    /* get uptime */
#ifdef HPUX
    pstat_static = sg_get_pstat_static();
    if (pstat_static == NULL) {
        return NULL;
    }

    currtime = time(NULL);

    boottime = pstat_static->boot_time;

    general_stat.uptime = currtime - boottime;
#endif
#ifdef SOLARIS
    if ((kc = kstat_open()) == NULL) {
        sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
        return NULL;
    }
    if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL) {
        sg_set_error(SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc");
        kstat_close(kc);
        return NULL;
    }
    if (kstat_read(kc, ksp, 0) == -1) {
        sg_set_error(SG_ERROR_KSTAT_READ, NULL);
        kstat_close(kc);
        return NULL;
    }
    if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL) {
        sg_set_error(SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time");
        kstat_close(kc);
        return NULL;
    }
    boottime=(kn->value.ui32);

    kstat_close(kc);

    time(&curtime);
    general_stat.uptime = curtime - boottime;
#endif
#if defined(LINUX) || defined(CYGWIN)
    if ((f=fopen("/proc/uptime", "r")) == NULL) {
        sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/uptime");
        return NULL;
    }
    if((fscanf(f,"%lu %*d",&general_stat.uptime)) != 1) {
        sg_set_error(SG_ERROR_PARSE, NULL);
        return NULL;
    }
    fclose(f);
#endif
#ifdef ALLBSD
    mib[0] = CTL_KERN;
    mib[1] = KERN_BOOTTIME;
    size = sizeof boottime;
    if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
        sg_set_error_with_errno(SG_ERROR_SYSCTL,
                                "CTL_KERN.KERN_BOOTTIME");
        return NULL;
    }
    time(&curtime);
    general_stat.uptime=curtime-boottime.tv_sec;
#endif
#ifdef WIN32
    if(read_counter_large(SG_WIN32_UPTIME, &result)) {
        sg_set_error(SG_ERROR_PDHREAD, PDH_UPTIME);
        return NULL;
    }
    general_stat.uptime = (time_t) result;
#endif

    return &general_stat;

}
int assoc_ServiceProcess( const CMPIBroker * _broker,
			  const CMPIContext * ctx,
			  const CMPIResult * rslt,
			  const CMPIObjectPath * ref,
			  int assocType,
			  CMPIStatus * rc )
{
  CMPIString     * sourceClass = NULL;
  CMPIData         serviceName;
  CMPIObjectPath * op          = NULL;
  CMPIObjectPath * rop         = NULL;
  CMPIInstance   * rci         = NULL;
  CMPIInstance   * sci         = NULL;
  LXS_Handle       lhdl;
  LXS_Service    * lxssvc      = NULL;
  int              i           = 0;

  _OSBASE_TRACE(2,("--- assoc_ServiceProcess() called"));

  /* check if source instance does exist */
  sci = CBGetInstance(_broker, ctx, ref, NULL, rc);
  if( sci == NULL ) {
    if( rc->rc == CMPI_RC_ERR_FAILED ) {
      CMSetStatusWithChars( _broker, rc,
			    CMPI_RC_ERR_FAILED, "GetInstance of source object failed.");
    }
    if( rc->rc == CMPI_RC_ERR_NOT_FOUND ) {
      CMSetStatusWithChars( _broker, rc,
			    CMPI_RC_ERR_NOT_FOUND, "Source object not found.");
    }
    _OSBASE_TRACE(2,("--- assoc_ServiceProcess() failed : %s",CMGetCharPtr(rc->msg)));
    return -1;
  }

  sourceClass = CMGetClassName(ref, rc);
  if (CMGetCharPtr(sourceClass) == NULL) {
    CMSetStatusWithChars( _broker, rc,
			  CMPI_RC_ERR_FAILED, "Could not get source class name.");
    _OSBASE_TRACE(2,("--- assoc_ServiceProcess() failed : %s",CMGetCharPtr(rc->msg)));
    return -1;
  }

  /* source class is Linux_UnixProcess; target class is Linux_Service */
  if( strcasecmp(CMGetCharPtr(sourceClass),_RefRightClass) == 0 ) {
    /* NOT_SUPPORTED - association is uni-directional */
  }
  /* source class is Linux_Service; target class is Linux_UnixProcess */
  else if( strcasecmp(CMGetCharPtr(sourceClass),_RefLeftClass) == 0 ) {

    serviceName = CMGetKey(ref, "Name", rc);
    if( serviceName.value.string == NULL ) { 
      CMSetStatusWithChars( _broker, rc, 
			    CMPI_RC_ERR_FAILED, "Could not get Name of Service" ); 
      _OSBASE_TRACE(2,("--- assoc_ServiceProcess() failed : %s",CMGetCharPtr(rc->msg)));
      return -1;
    }
    lhdl=LXS_InitFiltered(CMGetCharPtr(serviceName.value.string));
    if (lhdl==NULL) {
      _OSBASE_TRACE(2,("--- assoc_ServiceProcess() exited : Could not find associated Service."));
      return 0;
    }
    lxssvc=LXS_Next(lhdl);
    if (lxssvc==NULL) {
      _OSBASE_TRACE(2,("--- assoc_ServiceProcess() exited : Could not find associated Service."));
      return 0;
    }

    /* get the list of associated processe */
    for (i=0;lxssvc->svProcesses[i]!=NULL;i++) {

      op = CMNewObjectPath( _broker, CMGetCharPtr(CMGetNameSpace(ref,rc)), 
			    _RefRightClass, rc );
      if( CMIsNullObject(op) ) { 
	CMSetStatusWithChars( _broker, rc, 
			      CMPI_RC_ERR_FAILED, "Create CMPIObjectPath failed." ); 
	_OSBASE_TRACE(2,("--- assoc_ServiceProcess() failed : %s",CMGetCharPtr(rc->msg)));
	return -1;
      }
      CMAddKey(op, "CSCreationClassName", CSCreationClassName, CMPI_chars);
      CMAddKey(op, "CSName", get_system_name(), CMPI_chars);
      CMAddKey(op, "OSCreationClassName", OSCreationClassName, CMPI_chars);
      CMAddKey(op, "OSName", get_os_name(), CMPI_chars);
      CMAddKey(op, "CreationClassName", _RefRightClass, CMPI_chars);
      CMAddKey(op, "Handle", lxssvc->svProcesses[i], CMPI_chars);

      if (assocType&ATYPE_ASSOC) {
	/* the process (name) */
	if (assocType&ATYPE_NAME) {
	  CMReturnObjectPath(rslt, op); 
	}
	else {	  
	  rci = CBGetInstance(_broker, ctx, op, NULL, rc);
	  if(rci==NULL) { return -1; }
	  CMReturnInstance( rslt, rci );
	}
      } 
      else {
	/* the reference object (name) */
	if (assocType&ATYPE_NAME) {
	  rop = _makePath_ServiceProcess(_broker, ref, op, rc);
	  CMReturnObjectPath(rslt, rop); 
	} 
	else {
	  rci = _makeInst_ServiceProcess(_broker, ref, op, rc);
	  CMReturnInstance( rslt, rci );
	}
      }

    }
    LXS_Term(lhdl);
  }

  _OSBASE_TRACE(2,("--- assoc_ServiceProcess() exited"));
  return 0;
}
예제 #6
0
파일: export.cpp 프로젝트: avril-gh/godot
	virtual void get_platform_features(List<String> *r_features) {

		r_features->push_back("web");
		r_features->push_back(get_os_name());
	}
예제 #7
0
static int analyze_plot(sd_bus *bus) {
        struct unit_times *times;
        struct boot_times *boot;
        struct utsname name;
        int n, m = 1, y=0;
        double width;
        _cleanup_free_ char *pretty_times = NULL, *osname = NULL;
        struct unit_times *u;

        n = acquire_boot_times(bus, &boot);
        if (n < 0)
                return n;

        n = pretty_boot_time(bus, &pretty_times);
        if (n < 0)
                return n;

        get_os_name(&osname);
        assert_se(uname(&name) >= 0);

        n = acquire_time_data(bus, &times);
        if (n <= 0)
                return n;

        qsort(times, n, sizeof(struct unit_times), compare_unit_start);

        width = SCALE_X * (boot->firmware_time + boot->finish_time);
        if (width < 800.0)
                width = 800.0;

        if (boot->firmware_time > boot->loader_time)
                m++;
        if (boot->loader_time) {
                m++;
                if (width < 1000.0)
                        width = 1000.0;
        }
        if (boot->initrd_time)
                m++;
        if (boot->kernel_time)
                m++;

        for (u = times; u < times + n; u++) {
                double text_start, text_width;

                if (u->activating < boot->userspace_time ||
                    u->activating > boot->finish_time) {
                        free(u->name);
                        u->name = NULL;
                        continue;
                }

                /* If the text cannot fit on the left side then
                 * increase the svg width so it fits on the right.
                 * TODO: calculate the text width more accurately */
                text_width = 8.0 * strlen(u->name);
                text_start = (boot->firmware_time + u->activating) * SCALE_X;
                if (text_width > text_start && text_width + text_start > width)
                        width = text_width + text_start;

                if (u->deactivated > u->activating && u->deactivated <= boot->finish_time
                                && u->activated == 0 && u->deactivating == 0)
                        u->activated = u->deactivating = u->deactivated;
                if (u->activated < u->activating || u->activated > boot->finish_time)
                        u->activated = boot->finish_time;
                if (u->deactivating < u->activated || u->activated > boot->finish_time)
                        u->deactivating = boot->finish_time;
                if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time)
                        u->deactivated = boot->finish_time;
                m++;
        }

        svg("<?xml version=\"1.0\" standalone=\"no\"?>\n"
            "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
            "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");

        svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" "
            "xmlns=\"http://www.w3.org/2000/svg\">\n\n",
                        80.0 + width, 150.0 + (m * SCALE_Y) +
                        5 * SCALE_Y /* legend */);

        /* write some basic info as a comment, including some help */
        svg("<!-- This file is a systemd-analyze SVG file. It is best rendered in a   -->\n"
            "<!-- browser such as Chrome, Chromium or Firefox. Other applications     -->\n"
            "<!-- that render these files properly but much slower are ImageMagick,   -->\n"
            "<!-- gimp, inkscape, etc. To display the files on your system, just      -->\n"
            "<!-- point your browser to this file.                                    -->\n\n"
            "<!-- This plot was generated by systemd-analyze version %-16.16s -->\n\n", VERSION);

        /* style sheet */
        svg("<defs>\n  <style type=\"text/css\">\n    <![CDATA[\n"
            "      rect       { stroke-width: 1; stroke-opacity: 0; }\n"
            "      rect.background   { fill: rgb(255,255,255); }\n"
            "      rect.activating   { fill: rgb(255,0,0); fill-opacity: 0.7; }\n"
            "      rect.active       { fill: rgb(200,150,150); fill-opacity: 0.7; }\n"
            "      rect.deactivating { fill: rgb(150,100,100); fill-opacity: 0.7; }\n"
            "      rect.kernel       { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
            "      rect.initrd       { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
            "      rect.firmware     { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
            "      rect.loader       { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
            "      rect.userspace    { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
            "      rect.security     { fill: rgb(144,238,144); fill-opacity: 0.7; }\n"
            "      rect.generators   { fill: rgb(102,204,255); fill-opacity: 0.7; }\n"
            "      rect.unitsload    { fill: rgb( 82,184,255); fill-opacity: 0.7; }\n"
            "      rect.box   { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n"
            "      line       { stroke: rgb(64,64,64); stroke-width: 1; }\n"
            "//    line.sec1  { }\n"
            "      line.sec5  { stroke-width: 2; }\n"
            "      line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n"
            "      text       { font-family: Verdana, Helvetica; font-size: 14px; }\n"
            "      text.left  { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: start; }\n"
            "      text.right { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: end; }\n"
            "      text.sec   { font-size: 10px; }\n"
            "    ]]>\n   </style>\n</defs>\n\n");

        svg("<rect class=\"background\" width=\"100%%\" height=\"100%%\" />\n");
        svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
        svg("<text x=\"20\" y=\"30\">%s %s (%s %s) %s</text>",
            isempty(osname) ? "Linux" : osname,
            name.nodename, name.release, name.version, name.machine);

        svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
        svg_graph_box(m, -boot->firmware_time, boot->finish_time);

        if (boot->firmware_time) {
                svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y);
                svg_text(true, -(double) boot->firmware_time, y, "firmware");
                y++;
        }
        if (boot->loader_time) {
                svg_bar("loader", -(double) boot->loader_time, 0, y);
                svg_text(true, -(double) boot->loader_time, y, "loader");
                y++;
        }
        if (boot->kernel_time) {
                svg_bar("kernel", 0, boot->kernel_done_time, y);
                svg_text(true, 0, y, "kernel");
                y++;
        }
        if (boot->initrd_time) {
                svg_bar("initrd", boot->initrd_time, boot->userspace_time, y);
                svg_text(true, boot->initrd_time, y, "initrd");
                y++;
        }
        svg_bar("active", boot->userspace_time, boot->finish_time, y);
        svg_bar("security", boot->security_start_time, boot->security_finish_time, y);
        svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
        svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
        svg_text(true, boot->userspace_time, y, "systemd");
        y++;

        for (u = times; u < times + n; u++) {
                char ts[FORMAT_TIMESPAN_MAX];
                bool b;

                if (!u->name)
                        continue;

                svg_bar("activating",   u->activating, u->activated, y);
                svg_bar("active",       u->activated, u->deactivating, y);
                svg_bar("deactivating", u->deactivating, u->deactivated, y);

                /* place the text on the left if we have passed the half of the svg width */
                b = u->activating * SCALE_X < width / 2;
                if (u->time)
                        svg_text(b, u->activating, y, "%s (%s)",
                                 u->name, format_timespan(ts, sizeof(ts), u->time, USEC_PER_MSEC));
                else
                        svg_text(b, u->activating, y, "%s", u->name);
                y++;
        }

        /* Legend */
        y++;
        svg_bar("activating", 0, 300000, y);
        svg_text(true, 400000, y, "Activating");
        y++;
        svg_bar("active", 0, 300000, y);
        svg_text(true, 400000, y, "Active");
        y++;
        svg_bar("deactivating", 0, 300000, y);
        svg_text(true, 400000, y, "Deactivating");
        y++;
        svg_bar("security", 0, 300000, y);
        svg_text(true, 400000, y, "Setting up security module");
        y++;
        svg_bar("generators", 0, 300000, y);
        svg_text(true, 400000, y, "Generators");
        y++;
        svg_bar("unitsload", 0, 300000, y);
        svg_text(true, 400000, y, "Loading unit files");
        y++;

        svg("</g>\n\n");

        svg("</svg>\n");

        free_unit_times(times, (unsigned) n);

        return 0;
}
예제 #8
0
static sg_error
sg_get_host_info_int(sg_host_info *host_info_buf) {

#ifdef WIN32
	unsigned long nameln;
	char *name;
	long long result;
	OSVERSIONINFOEX osinfo;
	SYSTEM_INFO sysinfo;
	char *tmp_name;
	char tmp[10];
#else
	struct utsname os;
# if defined(HPUX)
	struct pst_static pstat_static;
	struct pst_dynamic pstat_dynamic;
	time_t currtime;
	long boottime;
# elif defined(SOLARIS)
	time_t boottime, curtime;
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_named_t *kn;
	char *isainfo = NULL;
	long isabufsz, rc;
# elif defined(LINUX) || defined(CYGWIN)
	FILE *f;
# elif defined(ALLBSD)
	int mib[2];
	struct timeval boottime;
	time_t curtime;
	size_t size;
	int ncpus;
#  if defined(HW_MACHINE_ARCH) || defined(HW_MACHINE)
	char arch_name[16];
#  endif
# elif defined(AIX)
	static perfstat_cpu_total_t cpu_total;
	sg_error rc;
#  if defined(HAVE_GETUTXENT)
	struct utmpx *ut;
#  else
	struct utmp *ut;
#  endif
# endif
#endif

	host_info_buf->ncpus = 0;
	host_info_buf->maxcpus = 0;
	host_info_buf->bitwidth = 0;
	host_info_buf->host_state = sg_unknown_configuration;
	host_info_buf->uptime = 0;
	host_info_buf->systime = 0;

#ifdef WIN32
	/* these settings are static after boot, so why get them
	 * constantly?
	 *
	 * Because we want to know some changes anyway - at least
	 * when the hostname (DNS?) changes
	 */

	/* get system name */
	nameln = MAX_COMPUTERNAME_LENGTH + 1;
	name = sg_malloc(nameln);
	if(name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/*
	 * XXX probably GetComputerNameEx() is a better entry point ...
	 */
	if( GetComputerName(name, &nameln) == 0 ) {
		free(name);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetComputerName");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, name)) {
		free(name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(name);

	/* get OS name, version and build */
	ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX));
	osinfo.dwOSVersionInfoSize = sizeof(osinfo);
	if(!GetVersionEx(&osinfo)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetVersionEx");
	}
	GetSystemInfo(&sysinfo);

	/* Release - single number */
	if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SPRINTF, NULL);
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* Version */
	/* usually a single digit . single digit, eg 5.0 */
	if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion,
				osinfo.dwMinorVersion) == -1) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* OS name */
	tmp_name = get_os_name(osinfo, sysinfo);
	if(tmp_name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, tmp_name)) {
		free(tmp_name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(tmp_name);

	/* Platform */
	switch(sysinfo.wProcessorArchitecture) {
		case PROCESSOR_ARCHITECTURE_INTEL:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Intel")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_IA64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"IA64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_AMD64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"AMD64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		default:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Unknown")){
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
	}

	if(read_counter_large(SG_WIN32_UPTIME, &result)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PDHREAD, PDH_UPTIME);
	}

	host_info_buf->uptime = (time_t) result;
#else
	if((uname(&os)) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_UNAME, NULL);
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, os.sysname)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, os.release)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, os.version)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, os.machine)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, os.nodename)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* get uptime */
#ifdef HPUX
	if (pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_static");
	}

	if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_dynamic");
	}

	currtime = time(NULL);

	boottime = pstat_static.boot_time;

	host_info_buf->uptime = currtime - boottime;
	host_info_buf->ncpus = pstat_dynamic.psd_proc_cnt;
	host_info_buf->maxcpus = pstat_dynamic.psd_max_proc_cnt;
	host_info_buf->bitwidth = sysconf(_SC_KERNEL_BITS);

	/*
	 * TODO: getting virtualization state
	 *       1) on boostrapping this component, try loading /opt/hpvm/lib/libhpvm.so (or so)
	 *       2) get function addresses for
	 *          a) HPVM_boolean hpvm_api_server_check()
	 *          b) HPVM_boolean hpvm_api_virtmach_check()
	 *
	 * Seems to be hardware virtualization ...
	 * See: http://docstore.mik.ua/manuals/hp-ux/en/T2767-90141/index.html (hpvmpubapi(3))
	 *      http://jreypo.wordpress.com/tag/hpvm/
	 *      http://jreypo.wordpress.com/category/hp-ux/page/3/
	 *      http://h20338.www2.hp.com/enterprise/us/en/os/hpux11i-partitioning-integrity-vm.html
	 */

#elif defined(SOLARIS)
	if ((kc = kstat_open()) == NULL) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_OPEN, NULL);
	}

	if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc");
	}
	if (kstat_read(kc, ksp, 0) == -1) {
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_READ, NULL);
	}
	if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time");
	}
	/* XXX verify on Solaris 10 if it's still ui32 */
	boottime = (kn->value.ui32);

	kstat_close(kc);

	time(&curtime);
	host_info_buf->uptime = curtime - boottime;

	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	isainfo = sg_malloc( isabufsz = (32 * sizeof(*isainfo)) );
	if( NULL == isainfo ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
# define MKSTR(x) #x
# if defined(SI_ARCHITECTURE_K)
#  define SYSINFO_CMD SI_ARCHITECTURE_K
# elif defined(SI_ISALIST)
#  define SYSINFO_CMD SI_ISALIST
# else
#  define SYSINFO_CMD SI_ARCHITECTURE
# endif
sysinfo_again:
	if( -1 == ( rc = sysinfo( SYSINFO_CMD, isainfo, isabufsz ) ) ) {
		free(isainfo);
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSINFO, MKSTR(SYSINFO_CMD) );
	}
	else if( rc > isabufsz ) {
		char *tmp = sg_realloc(isainfo, rc);
		if( NULL == tmp ) {
			free(isainfo);
			RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
		}
		isabufsz = rc;
		isainfo = tmp;
		goto sysinfo_again;
	}

	host_info_buf->bitwidth = get_bitwidth_by_arch_name(isainfo);
	free(isainfo);
	host_info_buf->host_state = sg_unknown_configuration;

#elif defined(LINUX) || defined(CYGWIN)
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_OPEN, "/proc/uptime");
	}

#define TIME_T_SCANF_FMT (sizeof(int[(((time_t)-1)/2)%4+1]) == sizeof(int[1]) ? "%ld %*d" : "%lu %*d" )
	if((fscanf(f,TIME_T_SCANF_FMT,&host_info_buf->uptime)) != 1){
		fclose(f);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PARSE, NULL);
	}
	fclose(f);

# if defined(LINUX)
	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	if( access( "/proc/sys/kernel/vsyscall64", F_OK ) == 0 ||
	    access( "/proc/sys/abi/vsyscall32", F_OK ) == 0 ) {
		host_info_buf->bitwidth = 64;
	}
	else {
		host_info_buf->bitwidth = sysconf(_SC_LONG_BIT); // well, maybe 64-bit disabled 128-bit system o.O
	}
	host_info_buf->host_state = sg_unknown_configuration;
# endif

#elif defined(ALLBSD)
	mib[0] = CTL_KERN;
	mib[1] = KERN_BOOTTIME;
	size = sizeof(boottime);
	if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_KERN.KERN_BOOTTIME");
	}
	time(&curtime);
	host_info_buf->uptime= curtime - boottime.tv_sec;

# if defined(HW_NCPU)
	mib[0] = CTL_HW;
	mib[1] = HW_NCPU;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPU" );
	}
# endif
# if defined(HW_MACHINE_ARCH)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE_ARCH;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
# endif
# if defined(HW_MACHINE)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE" );
	}
# elif defined(HW_MACHINE_ARCH)
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE_ARCH" );
# endif
# if defined(HW_MACHINE_ARCH)
	}
# endif
	host_info_buf->host_state = sg_unknown_configuration; /* details must be analysed "manually", no syscall */
	host_info_buf->maxcpus = (unsigned)ncpus;
# if defined(HW_NCPUONLINE)
	/* use knowledge about number of cpu's online, when available instead of assuming all of them */
	mib[0] = CTL_HW;
	mib[1] = HW_NCPUONLINE;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPUONLINE" );
	}
# endif
	host_info_buf->ncpus = (unsigned)ncpus;

#elif defined(AIX)
	if(perfstat_cpu_total(NULL, &cpu_total, sizeof(cpu_total), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "perfstat_cpu_total");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, cpu_total.description)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	host_info_buf->ncpus = cpu_total.ncpus;
	host_info_buf->maxcpus = cpu_total.ncpus_cfg;
	host_info_buf->bitwidth = sysconf(_SC_AIX_KERNEL_BITMODE);
	if( sysconf(_SC_LPAR_ENABLED) > 0 ) {
		host_info_buf->host_state = sg_hardware_virtualized;
	}
	else {
		host_info_buf->host_state = sg_physical_host;
	}

#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_lock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
# if defined(HAVE_GETUTXENT)
#  define UTENTFN getutxent
#  define UTENTTM ut->ut_tv.tv_sec
	setutxent();
# else
#  define UTENTFN getutent
#  define UTENTTM ut->ut_time
	setutent();
# endif
	while( NULL != ( ut = UTENTFN() ) ) {
		if( ut->ut_type == BOOT_TIME ) {
			host_info_buf->uptime = time(NULL) - UTENTTM;
			break;
		}
	}
# if defined(HAVE_GETUTXENT)
	endutxent();
# else
	endutent();
# endif
#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_unlock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
#else
	RETURN_WITH_SET_ERROR("os", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif
#endif /* WIN32 */

	host_info_buf->systime = time(NULL);

	return SG_ERROR_NONE;
}