getgrent#
קריאת הרשומה הבאה ממסד הנתונים של קבוצות המערכת.
getgrent עובר על מסד הנתונים של הקבוצות במארח רשומה אחת בכל פעם, כפי שלולאה רגילה על /etc/group הייתה קוראת אותו שורה־שורה, ומחזיר תצוגה בצורת Perl של כל רשומה. זוהי צורת האיטרטור של חיפושי הקבוצות - יש להשתמש בה כאשר רוצים כל קבוצה, או כל קבוצה התואמת לתנאי כלשהו. לחיפוש רשומה בודדת לפי שם או gid, יש לפנות במקום זאת ל־getgrnam או getgrgid.
קריאה ראשונה ל־getgrent פותחת את מסד הנתונים באופן מרומז. האיטרציה ממשיכה לאורך קריאות נוספות עד שמסד הנתונים מתרוקן, ואז getgrent מחזיר את הרשימה הריקה (או undef בהקשר סקלר). יש לקרוא ל־setgrent כדי לחזור להתחלה, או ל־endgrent כדי לסגור את מסד הנתונים ולשחרר משאבים שספריית C מחזיקה.
תקציר#
my ($name, $passwd, $gid, $members) = getgrent;
my $name = getgrent; # scalar context
מה מקבלים בחזרה#
בהקשר רשימה, רשימה בת ארבעה איברים - רשומה אחת לכל קבוצה:
אינדקס | שדה | משמעות |
|---|---|---|
0 |
| שם קבוצה (לדוגמה |
1 |
| סיסמת קבוצה, בדרך כלל |
2 |
| gid מספרי |
3 |
| מחרוזת מופרדת ברווחים של שמות login של החברים |
כאשר האיטרציה חוצה את הסוף, ההחזרה היא הרשימה הריקה. אם כותבים if (my @gr = getgrent) הלולאה מסתיימת בצורה נקייה בסוף מסד הנתונים.
בהקשר סקלר, getgrent מחזיר רק את $name. כאשר מסד הנתונים מתרוקן, הוא מחזיר undef - שזהו האות שרוב הסקריפטים בודקים מולו כדי לסיים לולאת while.
$members הוא מחרוזת רגילה, לא מערך. יש לפצל אותה על רווחים כאשר נדרשת הרשימה:
my @logins = split ' ', $members;
מצב גלובלי שהוא נוגע בו#
getgrent שומר מצב איטרציה לכל־תהליך בתוך ספריית C (קונספטואלית עמדה בקובץ בתוך מסד נתוני הקבוצות). שתי קריאות באותו תהליך חולקות את המצב הזה; לולאה מקוננת הקוראת ל־getgrent בתוך לולאת getgrent אחרת תשלב רשומות ותפספס את רובן. יש לסדר את המעברים בטור, או לקלוט תחילה את כל הרשומות למערך:
my @all;
while (my @gr = getgrent) { push @all, [ @gr ] }
endgrent;
האיטרטור אינו מאופס כאשר תת־שגרה חוזרת. אם קוד ספרייה שאינך שולט בו קורא ל־getgrent, הוא מזיז את העמדה שלך. יש להישמר עם setgrent כאשר נדרשת התחלה נקייה.
דוגמאות#
מעבר על כל קבוצה והדפסת השם ומספר החברים:
while (my ($name, undef, $gid, $members) = getgrent) {
my $n = length $members ? scalar(split ' ', $members) : 0;
printf "%-16s gid=%d members=%d\n", $name, $gid, $n;
}
endgrent;
איסוף כל הקבוצות ש־login נתון שייך אליהן:
my $user = 'alice';
my @groups;
while (my ($name, undef, undef, $members) = getgrent) {
push @groups, $name
if grep { $_ eq $user } split ' ', $members;
}
endgrent;
הקשר סקלר - מנייה של כל שמות הקבוצות, אחד בכל שורה:
while (defined(my $name = getgrent)) {
print $name, "\n";
}
endgrent;
חזרה לאחור וקריאה מחדש, לדוגמה לבניית שני אינדקסים במעבר אחד כל אחד:
setgrent;
my %by_name = map { $_->[0] => $_ }
map { [ getgrent ] } 1 .. (); # collect…
# …or just loop twice with an explicit setgrent before each pass.
setgrent;
while (my @gr = getgrent) { ... }
endgrent;
המרת gid מספרי מ־stat לשם קבוצה ללא חיפוש שני על־ידי שמירה במטמון של פלט האיטרטור:
my %name_of;
while (my ($name, undef, $gid) = getgrent) {
$name_of{$gid} = $name;
}
endgrent;
my $gid = (stat $path)[5];
print "group: $name_of{$gid}\n";
מקרי קצה#
סוף האיטרציה מול רשומה אמיתית: בהקשר רשימה, מסד נתונים שהתרוקן מחזיר את הרשימה הריקה - שמוקצת כאפס איברים, כך ש־
my @gr = getgrent; @gr or last;הוא בדיקת הסיום האידיומטית. בהקשר סקלר, יש לבדוק עםdefinedולא עם אמיתיות, מאחר ששם קבוצה לגיטימי יכול בעיקרון להיות המחרוזת"0".אין שדה סיסמה ב־Linux מודרני:
$passwdהוא כמעט תמיד"x"(ה־hashes האמיתיים חיים ב־/etc/gshadow). אין להתייחס לערך שאינו"x"כ“סיסמה מוגדרת“ מבלי להתייעץ עם מסד הנתונים shadow.$membersריק: לקבוצות ללא חברים מפורשים (משתמשים הרשומים רק לפי gid ראשי)$membersהוא המחרוזת הריקה.split ' ', ""מחזיר רשימה ריקה - הדרך האידיומטית לקבל חברים כמערך ללא מקרה מיוחד.חברות מרומזת לפי primary-gid אינה מדווחת:
$membersמציג רק את המשתמשים הנקובים במפורש ברשומת/etc/groupשל הקבוצה. משתמש שה־primary gid שלו תואם לקבוצה הזו אך אינו רשום גם בשדהmembersאינו מופיע. יש להצליב עםgetpwentאם נדרשים שני סוגי החברות.איטרציה מקוננת הורסת את העמדה: לולאת
getgrentשנייה שמתחילה לפני שהראשונה מסתיימת חולקת את אותו סמן. יש להשתמש ב־setgrentבין מעברים, או לקלוט תחילה תמונת מצב של מסד הנתונים לזיכרון.מצב taint: השדה
$passwdמסומן כ־tainted תחת-T, בדומה ל־getpwent- יש להתייחס אליו כקלט בלתי־אמין על אף שהערך הרגיל הוא"x".ברמת תהליך, לא ברמת thread: במערכות ללא וריאנטים בטוחים ל־threads, מצב האיטרציה הוא לכל־תהליך, לא לכל־thread. שני threads שמהלכים על
getgrentבו־זמנית יפספסו רשומות.endgrentאופציונלי אך מנומס: השארת מסד הנתונים פתוח עד יציאת התוכנית עובדת, אך אם סיימת לאיטר, יש לקרוא ל־endgrentכדי שספריית C תוכל לוותר על המאגרים שלה.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
getgrnam- חיפוש בודד לפי שם קבוצה; לשימוש כאשר השם כבר ידוע ונרצית רק רשומה אחתgetgrgid- חיפוש בודד לפי gid מספרי; השותף הרגיל שלstatכאשר נדרש שם קבוצה עבור קובץsetgrent- חזרה לאחור של האיטרטור להתחלת מסד הנתונים של הקבוצות לפני מעבר סריקה מלאה נוסףendgrent- סגירת מסד הנתונים ושחרור משאבים שספריית C מחזיקה פתוחיםgetpwent- האיטרטור המקביל על מסד הנתונים passwd; יש לשלב עםgetgrentבעת פתרון יחסי משתמש־לקבוצה מלאיםscalar- אילוץ הקשר סקלר כאשר נדרש רק שם הקבוצה ורוצים לדלג על השדות האחרים