Bug 135179

Summary: "GID" column header for PGID is confusing with EGID
Product: [Applications] ksysguard Reporter: Philippe Cloutier <chealer>
Component: generalAssignee: KSysGuard Developers <ksysguard-bugs>
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Debian testing   
OS: Linux   
Latest Commit: Version Fixed In:

Description Philippe Cloutier 2006-10-06 06:50:17 UTC
Version:            (using KDE KDE 3.5.4)
Installed from:    Debian testing/unstable Packages
OS:                Linux

Labeling the column for PGID as "GID" is confusing with EGID. It should be renamed to PGID.

The person from whom this request originates also suggests adding a column for EGID ;)
Comment 1 Bram Schoenmakers 2006-10-06 18:27:38 UTC
Please create a new report about the EGID suggestion.
Comment 2 John Tapsell 2006-11-23 13:04:20 UTC
Hmm, so there's effective GID and the process GID.

The GID it shows should indeed be the EGID it seems.  Is this what other apps do?
Comment 3 Philippe Cloutier 2006-11-23 14:13:59 UTC
It's what ps does. But there are so many ?GID-s that it may be a good idea to avoid having a "GID".
Comment 4 John Tapsell 2007-03-26 15:47:03 UTC
SVN commit 646702 by johnflux:

Get the effective etc GIDs and UIDs for the process.

CCBUG: 135179


 M  +9 -1      process.h  
 M  +3 -3      processes_linux_p.cpp   [POSSIBLY UNSAFE: scanf]


--- trunk/KDE/kdebase/workspace/ksysguard/libksysguard/processcore/process.h #646701:646702
@@ -47,7 +47,15 @@
         Process *parent;
 
         long long uid; ///The user id that the process is running as
-        long long gid; ///The group id that the process is running as
+        long long euid; ///The effective user id that the process is running as
+        long long suid; ///The set user id that the process is running as
+        long long fsuid; ///The file system user id that the process is running as.
+
+        long long gid; ///The process group id that the process is running as
+        long long egid; ///The effective group id that the process is running as
+        long long sgid; ///The set group id that the process is running as
+        long long fsgid; ///The filesystem group id that the process is running as
+
         long long tracerpid; ///If this is being debugged, this is the process that is debugging it
 	QByteArray tty; /// The name of the tty the process owns
         long long userTime; ///The time, in 100ths of a second, spent in total on user calls. -1 if not known
--- trunk/KDE/kdebase/workspace/ksysguard/libksysguard/processcore/processes_linux_p.cpp #646701:646702
@@ -83,13 +83,13 @@
 	    break;
 	  case 'U': 
 	    if((unsigned int)size > sizeof("Uid:") && qstrncmp(mBuffer, "Uid:", sizeof("Uid:")-1) == 0) {
-		process->uid = atol(mBuffer + sizeof("Uid:")-1);
+		sscanf(mBuffer + sizeof("Uid:"), "%d %d %d %d", &process->uid, &process->euid, &process->suid, &process->fsuid );
 	        if(++found == 4) goto finish;
 	    }
 	    break;
 	  case 'G':
 	    if((unsigned int)size > sizeof("Gid:") && qstrncmp(mBuffer, "Gid:", sizeof("Gid:")-1) == 0) {
-		process->gid = atol(mBuffer + sizeof("Gid:")-1);
+		sscanf(mBuffer + sizeof("Gid:"), "%d %d %d %d", &process->gid, &process->egid, &process->sgid, &process->fsgid );
 	        if(++found == 4) goto finish;
 	    }
 	    break;
@@ -258,7 +258,7 @@
 
     while(true) {
 	    if(word[0] == ' ' ) {
-		    if(++current_word == 2)
+		    if(++current_word == 2) //number of pages that are shared
 			    break;
 	    } else if(word[0] == 0) {
 	    	return false; //end of data - serious problem
Comment 5 John Tapsell 2007-03-26 23:11:48 UTC
SVN commit 646905 by johnflux:

Show the effective etc UID/GID in the tooltip for the username
CCBUG:135179


 M  +59 -35    ProcessModel.cc  
 M  +11 -5     ProcessModel.h  


--- trunk/KDE/kdebase/workspace/ksysguard/libksysguard/processui/ProcessModel.cc #646904:646905
@@ -385,37 +385,47 @@
 	return true;
 }
 
-QString ProcessModel::getTooltipForUser(long long uid, long long gid) const
+QString ProcessModel::getTooltipForUser(const KSysGuard::Process *ps) const
 {
-	QString &userTooltip = mUserTooltips[uid];
-	if(userTooltip.isEmpty()) {
-		if(!mIsLocalhost) {
-			QVariant username = getUsernameForUser(uid);
+	QString userTooltip;
+	if(!mIsLocalhost) {
+		userTooltip = "<qt>";
+		userTooltip += i18n("Login Name: %1<br/>", getUsernameForUser(ps->uid, true));
+	} else {
+		KUser user(ps->uid);
+		if(!user.isValid())
+			userTooltip = i18n("This user is not recognised for some reason");
+		else {
 			userTooltip = "<qt>";
-			userTooltip += i18n("Login Name: %1<br/>", username.toString());
-			userTooltip += i18n("User ID: %1", (long int)uid);
-		} else {
-			KUser user(uid);
-			if(!user.isValid())
-				userTooltip = i18n("This user is not recognised for some reason");
-			else {
-				userTooltip = "<qt>";
-				if(!user.fullName().isEmpty()) userTooltip += i18n("<b>%1</b><br/>", user.fullName());
-				userTooltip += i18n("Login Name: %1<br/>", user.loginName());
-				if(!user.roomNumber().isEmpty()) userTooltip += i18n("Room Number: %1<br/>", user.roomNumber());
-				if(!user.workPhone().isEmpty()) userTooltip += i18n("Work Phone: %1<br/>", user.workPhone());
-				userTooltip += i18n("User ID: %1", (long int)uid);
-			}
+			if(!user.fullName().isEmpty()) userTooltip += i18n("<b>%1</b><br/>", user.fullName());
+			userTooltip += i18n("Login Name: %1 (Uid: %2)<br/>", user.loginName(), ps->uid);
+			if(!user.roomNumber().isEmpty()) userTooltip += i18n("  Room Number: %1<br/>", user.roomNumber());
+			if(!user.workPhone().isEmpty()) userTooltip += i18n("  Work Phone: %1<br/>", user.workPhone());
 		}
 	}
-	if(gid != -1) {
-		if(!mIsLocalhost)
-			return userTooltip + i18n("<br/>Group ID: %1", (long int)gid);
-		QString groupname = KUserGroup(gid).name();
-		if(groupname.isEmpty())
-			return userTooltip + i18n("<br/>Group ID: %1", (long int)gid);
-		return userTooltip +  i18n("<br/>Group Name: %1", groupname)+ i18n("<br/>Group ID: %1", (long int)gid);
+	if( (ps->uid != ps->euid && ps->euid != -1) || 
+                   (ps->uid != ps->suid && ps->suid != -1) || 
+                   (ps->uid != ps->fsuid && ps->fsuid != -1)) {
+		if(ps->euid != -1) 
+			userTooltip += i18n("Effective User: %1<br/>", getUsernameForUser(ps->euid, true));
+		if(ps->suid != -1)
+			userTooltip += i18n("Setuid User: %1<br/>", getUsernameForUser(ps->suid, true));
+		if(ps->fsuid != -1)
+			userTooltip += i18n("File System User: %1<br/>", getUsernameForUser(ps->fsuid, true));
 	}
+	if(ps->gid != -1) {
+		userTooltip += i18n("<br/>Group: %1", getGroupnameForGroup(ps->gid));
+		if( (ps->gid != ps->egid && ps->egid != -1) || 
+	                   (ps->gid != ps->sgid && ps->sgid != -1) || 
+	                   (ps->gid != ps->fsgid && ps->fsgid != -1)) {
+			if(ps->egid != -1) 
+				userTooltip += i18n("<br/>Effective Group: %1", getGroupnameForGroup(ps->egid));
+			if(ps->sgid != -1)
+				userTooltip += i18n("<br/>Setuid Group: %1", getGroupnameForGroup(ps->sgid));
+			if(ps->fsgid != -1)
+				userTooltip += i18n("<br/>File System Group: %1", getGroupnameForGroup(ps->fsgid));
+		}
+	}
 	return userTooltip;
 }
 
@@ -423,18 +433,32 @@
 	return i18nc("Short description of a process. PID, name", "%1: %2", (long)(process->pid), process->name);
 }
 
-QVariant ProcessModel::getUsernameForUser(long long uid) const {
-	QVariant &username = mUserUsername[uid];
-	if(!username.isValid()) {
+QString ProcessModel::getGroupnameForGroup(long long gid) const {
+	if(mIsLocalhost) {
+		QString groupname = KUserGroup(gid).name();
+		if(!groupname.isEmpty())
+			return i18n("%1 (Gid: %2)", groupname, QString::number(gid));
+	}
+	return QString::number(gid);
+}
+
+QString ProcessModel::getUsernameForUser(long long uid, bool withuid) const {
+	QString &username = mUserUsername[uid];
+	if(username.isNull()) {
 		if(!mIsLocalhost) {
-			username = uid;
+			username = ""; //empty, but not null
 		} else {
 			KUser user(uid);
 			if(!user.isValid())
-				username = uid;
-			username = user.loginName();
+				username = "";
+			else
+				username = user.loginName();
 		}
 	}
+	if(username.isEmpty()) 
+		return QString::number(uid);
+	if(withuid)
+		return i18n("%1 (Uid: %2)", username, (long int)uid);
 	return username;
 }
 
@@ -457,7 +481,7 @@
 		case HeadingName:
 			return process->name;
 		case HeadingUser:
-			return getUsernameForUser(process->uid);
+			return getUsernameForUser(process->uid, false);
 		case HeadingNiceness:
 			return process->niceLevel;
 		case HeadingTty:
@@ -537,8 +561,8 @@
 		}
 		case HeadingUser: {
 			if(!tracer.isEmpty())
-				return getTooltipForUser(process->uid, process->gid) + "<br/>" + tracer;
-			return getTooltipForUser(process->uid, process->gid);
+				return getTooltipForUser(process) + "<br/>" + tracer;
+			return getTooltipForUser(process);
 		}
 		case HeadingNiceness:
 			return i18n("<br/>Nice level: %1 (%2)", QString::number(process->niceLevel), process->niceLevelAsString() );
--- trunk/KDE/kdebase/workspace/ksysguard/libksysguard/processui/ProcessModel.h #646904:646905
@@ -154,15 +154,21 @@
 	 *  This will be slow the first time, as it practically indirectly reads the whole of /etc/passwd
 	 *  But the second time will be as fast as hash lookup as we cache the result
 	 */
-	inline QString getTooltipForUser(long long uid, long long gid) const;
+	inline QString getTooltipForUser(const KSysGuard::Process *process) const;
 
-	/** Return a username (as a QString) for a local user if it can, otherwise just their uid (as a long long).
+	/** Return a username for a local user if it can, otherwise just their uid.
 	 *  This may have been given from the result of "ps" (but not necessarily).  If it's not found, then it
 	 *  needs to find out the username from the uid. This will be slow the first time, as it practically indirectly reads the whole of /etc/passwd
 	 *  But the second time will be as fast as hash lookup as we cache the result
+	 *
+	 *  If withuid is set, and the username is found, return: "username (Uid: uid)"
 	 */
-	inline QVariant getUsernameForUser(long long uid) const;
+	inline QString getUsernameForUser(long long uid, bool withuid) const;
 
+	/** Return the groupname for a given gid.  This is in the form of "gid" if not known, or
+	 *  "groupname (Uid: gid)" if known.
+	 */
+	inline QString getGroupnameForGroup(long long gid) const;
 	/** @see setIsLocalhost */
 	bool mIsLocalhost;
 
@@ -170,9 +176,9 @@
 	 *  @see getTooltipForUser */
 	mutable QHash<long long,QString> mUserTooltips;
 
-	/** A caching hash for (QString) username for a user uid, or just their uid if it can't be found (as a long long)
+	/** A caching hash for username for a user uid, or just their uid if it can't be found (as a long long)
 	 *  @see getUsernameForUser */
-	mutable QHash<long long, QVariant> mUserUsername;
+	mutable QHash<long long, QString> mUserUsername;
 
 	/** A mapping of a user id to whether this user can log in.  We have to guess based on the shell. All are set to true to non localhost.
 	 *  It is set to:
Comment 6 John Tapsell 2007-03-26 23:53:26 UTC
SVN commit 646926 by johnflux:

Use a comma to seperate the usernames

BUG:135179


 M  +1 -1      ProcessFilter.cc  
 M  +1 -1      ProcessModel.cc  


--- trunk/KDE/kdebase/workspace/ksysguard/libksysguard/processui/ProcessFilter.cc #646925:646926
@@ -73,7 +73,7 @@
 	case PROCESS_FILTER_ALL_SIMPLE:
 		break;
         case PROCESS_FILTER_SYSTEM:
-                if( uid >= 100 && model->canUserLogin(uid)))
+                if( uid >= 100 && model->canUserLogin(uid))
 			accepted = false;
 		break;
         case PROCESS_FILTER_USER:
--- trunk/KDE/kdebase/workspace/ksysguard/libksysguard/processui/ProcessModel.cc #646925:646926
@@ -484,7 +484,7 @@
 			if(process->uid == process->euid)
 				return getUsernameForUser(process->uid, false);
 			else
-				return getUsernameForUser(process->uid, false) + "/" + getUsernameForUser(process->euid, false);
+				return getUsernameForUser(process->uid, false) + ',' + getUsernameForUser(process->euid, false);
 		case HeadingNiceness:
 			return process->niceLevel;
 		case HeadingTty: