// // aegis - project change supervisor // Copyright (C) 1999, 2001-2009, 2011-2014 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static col::pointer colp; static output::pointer list_locks_name_col; static output::pointer list_locks_type_col; static output::pointer list_locks_project_col; static output::pointer list_locks_change_col; static output::pointer list_locks_address_col; static output::pointer list_locks_process_col; static string_list_ty list_locks_pnames; static long list_locks_count; static void list_locks_callback(lock_walk_found *found) { const char *name_str; const char *type_str; const char *project_str; long change_number; size_t j; static itab_ty *user_name_by_uid; string_ty *s; list_locks_count++; name_str = "unknown"; switch (found->name) { case lock_walk_name_master: name_str = "master"; break; case lock_walk_name_gstate: name_str = "gonzo"; break; case lock_walk_name_pstate: name_str = "project"; break; case lock_walk_name_cstate: name_str = "change"; break; case lock_walk_name_ustate: name_str = "user"; break; case lock_walk_name_baseline: name_str = "baseline"; break; case lock_walk_name_baseline_priority: name_str = "baseline priority"; break; case lock_walk_name_history: name_str = "history"; break; case lock_walk_name_unknown: break; } type_str = "unknown"; switch (found->type) { case lock_walk_type_shared: type_str = "shared"; break; case lock_walk_type_exclusive: type_str = "exclusive"; break; case lock_walk_type_unknown: break; } project_str = 0; change_number = 0; trace(("looking for found->subset 0x%04x\n", (unsigned)found->subset)); switch (found->name) { case lock_walk_name_pstate: case lock_walk_name_baseline: case lock_walk_name_baseline_priority: case lock_walk_name_history: for (j = 0; j < list_locks_pnames.size(); ++j) { s = list_locks_pnames[j]; trace(("project %s (0x%04x)\n", s->str_text, (unsigned)s->str_hash)); if ((s->str_hash & 0xFFFF) == (unsigned)found->subset) { project_str = s->str_text; break; } } if (!project_str) project_str = "unknown"; break; case lock_walk_name_cstate: for (j = 0; j < list_locks_pnames.size() && !change_number; ++j) { s = list_locks_pnames[j]; project *pp = project_alloc(s); if (!pp->bind_existing_errok()) { pp->free(); continue; } // // This is very messy, because the change // number is added to the project name hash. // // Use (mod 2**16) arithmetic, that's how its done. // Should bring this out in lock.h if ever change. // long cn = (found->subset - s->str_hash) & 0xFFFF; trace(("project %s (0x%04x), change %ld (0x%04x)\n", s->str_text, (unsigned)s->str_hash, cn, (unsigned)cn)); change::pointer cp = change::create(pp, cn); bool exists = cp->bind_existing_errok(); if (exists) { // A change with this change number exists in the // project. Note that there could be more than one // {project, change} combination that produces this // lock number, and this code reports only the first // one found. project_str = s->str_text; change_number = magic_zero_encode(cn); } pp->free(); } if (!project_str) project_str = "unknown"; break; case lock_walk_name_ustate: // This is the UID change_number = found->subset; if (!user_name_by_uid) { user_name_by_uid = itab_alloc(); setpwent(); for (;;) { struct passwd *pw; pw = getpwent(); if (!pw) break; s = str_from_c(pw->pw_name); itab_assign(user_name_by_uid, pw->pw_uid, s); } endpwent(); } s = (string_ty *)itab_query(user_name_by_uid, change_number); project_str = s ? s->str_text : "unknown"; break; case lock_walk_name_master: case lock_walk_name_gstate: case lock_walk_name_unknown: break; } // // print it all out // list_locks_name_col->fputs(name_str); list_locks_type_col->fputs(type_str); if (project_str) list_locks_project_col->fputs(project_str); if (change_number) { list_locks_change_col->fprintf ( "%4ld", magic_zero_decode(change_number) ); } list_locks_address_col->fprintf("%8.8lX", found->address); list_locks_process_col->fprintf("%5d", found->pid); if (!found->pid_is_local) list_locks_process_col->fputs(" remote"); colp->eoln(); } void list_locks(change_identifier &cid, string_list_ty *) { // // check for silly arguments // trace(("list_locks()\n{\n")); if (cid.project_is_set()) list_project_inappropriate(); if (cid.is_set()) list_change_inappropriate(); // // get the list of projects // project_list_get(&list_locks_pnames); // // open the columns // colp = col::open((string_ty *)0); colp->title("List of Locks", gonzo_lockpath_get()->str_text); list_locks_name_col = colp->create(0, 8, "Type\n------"); list_locks_type_col = colp->create(9, 19, "Mode\n------"); list_locks_project_col = colp->create(20, 32, "Project\n---------"); list_locks_change_col = colp->create(33, 40, "Change\n------"); list_locks_address_col = colp->create(41, 50, "Address\n--------"); list_locks_process_col = colp->create(51, 0, "Process\n--------"); list_locks_count = 0; // // list the locks found // lock_walk(list_locks_callback); if (list_locks_count == 0) { output::pointer info = colp->create(4, 0, (const char *)0); info->fputs("No locks found."); colp->eoln(); } trace(("}\n")); } // vim: set ts=8 sw=4 et :