plist.c revision 379
1#ifndef lint 2static const char *rcsid = "$Id: plist.c,v 1.6 1993/09/04 05:06:52 jkh Exp $"; 3#endif 4 5/* 6 * FreeBSD install - a package for the installation and maintainance 7 * of non-core utilities. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * Jordan K. Hubbard 19 * 18 July 1993 20 * 21 * General packing list routines. 22 * 23 */ 24 25#include "lib.h" 26 27/* Add an item to a packing list */ 28void 29add_plist(Package *p, plist_t type, char *arg) 30{ 31 PackingList tmp; 32 33 tmp = new_plist_entry(); 34 tmp->name = copy_string(arg); 35 tmp->type = type; 36 37 if (!p->head) 38 p->head = p->tail = tmp; 39 else { 40 tmp->prev = p->tail; 41 p->tail->next = tmp; 42 p->tail = tmp; 43 } 44} 45 46void 47add_plist_top(Package *p, plist_t type, char *arg) 48{ 49 PackingList tmp; 50 51 tmp = new_plist_entry(); 52 tmp->name = copy_string(arg); 53 tmp->type = type; 54 55 if (!p->head) 56 p->head = p->tail = tmp; 57 else { 58 tmp->next = p->head; 59 p->head->prev = tmp; 60 p->head = tmp; 61 } 62} 63 64/* Return the last (most recent) entry in a packing list */ 65PackingList 66last_plist(Package *p) 67{ 68 return p->tail; 69} 70 71/* Mark all items in a packing list to prevent iteration over them */ 72void 73mark_plist(Package *pkg) 74{ 75 PackingList p = pkg->head; 76 77 while (p) { 78 p->marked = TRUE; 79 p = p->next; 80 } 81} 82 83/* Return whether or not there is an item of 'type' in the list */ 84Boolean 85in_plist(Package *pkg, plist_t type) 86{ 87 PackingList p = pkg->head; 88 89 while (p) { 90 if (p->type == type) 91 return TRUE; 92 p = p->next; 93 } 94 return FALSE; 95} 96 97/* Allocate a new packing list entry */ 98PackingList 99new_plist_entry(void) 100{ 101 PackingList ret; 102 103 ret = (PackingList)malloc(sizeof(struct _plist)); 104 bzero(ret, sizeof(struct _plist)); 105 return ret; 106} 107 108/* Free an entire packing list */ 109void 110free_plist(Package *pkg) 111{ 112 PackingList p = pkg->head; 113 114 while (p) { 115 PackingList p1 = p->next; 116 117 free(p->name); 118 free(p); 119 p = p1; 120 } 121 pkg->head = pkg->tail = NULL; 122} 123 124/* 125 * For an ascii string denoting a plist command, return its code and 126 * optionally its argument(s) 127 */ 128int 129plist_cmd(char *s, char **arg) 130{ 131 char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */ 132 char *cp, *sp; 133 134 strcpy(cmd, s); 135 str_lowercase(cmd); 136 cp = cmd; 137 sp = s; 138 while (*cp) { 139 if (isspace(*cp)) { 140 *cp = '\0'; 141 while (isspace(*sp)) /* Never sure if macro, increment later */ 142 ++sp; 143 break; 144 } 145 ++cp, ++sp; 146 } 147 if (arg) 148 *arg = sp; 149 if (!strcmp(cmd, "cwd")) 150 return PLIST_CWD; 151 else if (!strcmp(cmd, "cd")) 152 return PLIST_CWD; 153 else if (!strcmp(cmd, "exec")) 154 return PLIST_CMD; 155 else if (!strcmp(cmd, "mode")) 156 return PLIST_CHMOD; 157 else if (!strcmp(cmd, "owner")) 158 return PLIST_CHOWN; 159 else if (!strcmp(cmd, "group")) 160 return PLIST_CHGRP; 161 else if (!strcmp(cmd, "comment")) 162 return PLIST_COMMENT; 163 else if (!strcmp(cmd, "ignore")) 164 return PLIST_IGNORE; 165 else if (!strcmp(cmd, "name")) 166 return PLIST_NAME; 167 else 168 return FAIL; 169} 170 171/* Read a packing list from a file */ 172void 173read_plist(Package *pkg, FILE *fp) 174{ 175 char *cp, pline[FILENAME_MAX]; 176 int cmd; 177 178 while (fgets(pline, FILENAME_MAX, fp)) { 179 int len = strlen(pline) - 1; 180 181 while (isspace(pline[len])) 182 pline[len--] = '\0'; 183 if (!len) 184 continue; 185 cp = pline; 186 if (pline[0] == CMD_CHAR) { 187 cmd = plist_cmd(pline + 1, &cp); 188 if (cmd == FAIL) 189 barf("Bad command '%s'", pline); 190 } 191 else 192 cmd = PLIST_FILE; 193 add_plist(pkg, cmd, cp); 194 } 195} 196 197/* Write a packing list to a file, converting commands to ascii equivs */ 198void 199write_plist(Package *pkg, FILE *fp) 200{ 201 PackingList plist = pkg->head; 202 203 while (plist) { 204 switch(plist->type) { 205 case PLIST_FILE: 206 fprintf(fp, "%s\n", plist->name); 207 break; 208 209 case PLIST_CWD: 210 fprintf(fp, "%ccwd %s\n", CMD_CHAR, plist->name); 211 break; 212 213 case PLIST_CMD: 214 fprintf(fp, "%cexec %s\n", CMD_CHAR, plist->name); 215 break; 216 217 case PLIST_CHMOD: 218 fprintf(fp, "%cchmod %s\n", CMD_CHAR, 219 plist->name ? plist->name : ""); 220 break; 221 222 case PLIST_CHOWN: 223 fprintf(fp, "%cchown %s\n", CMD_CHAR, 224 plist->name ? plist->name : ""); 225 break; 226 227 case PLIST_CHGRP: 228 fprintf(fp, "%cchgrp %s\n", CMD_CHAR, 229 plist->name ? plist->name : ""); 230 break; 231 232 case PLIST_COMMENT: 233 fprintf(fp, "%ccomment %s\n", CMD_CHAR, plist->name); 234 break; 235 236 case PLIST_IGNORE: 237 fprintf(fp, "%cignore\n", CMD_CHAR); 238 break; 239 240 case PLIST_NAME: 241 fprintf(fp, "%cname %s\n", CMD_CHAR, plist->name); 242 break; 243 244 default: 245 barf("Unknown command type %d (%s)\n", plist->type, plist->name); 246 break; 247 } 248 plist = plist->next; 249 } 250} 251 252/* Delete the results of a package installation, not the packaging itself */ 253void 254delete_package(Boolean ign_err, Package *pkg) 255{ 256 PackingList p = pkg->head; 257 char *Where = "."; 258 259 while (p) { 260 if (p->type == PLIST_CWD) { 261 Where = p->name; 262 if (Verbose) 263 printf("(CWD to %s)\n", Where); 264 } 265 else if (p->type == PLIST_IGNORE) 266 p = p->next; 267 else if (p->type == PLIST_FILE) { 268 char full_name[FILENAME_MAX]; 269 270 sprintf(full_name, "%s/%s", Where, p->name); 271 if (Verbose) 272 printf("Delete: %s\n", full_name); 273 274 if (!Fake && delete_hierarchy(full_name, ign_err)) 275 whinge("Unable to completely remove file '%s'", full_name); 276 } 277 p = p->next; 278 } 279} 280 281/* Selectively delete a hierarchy */ 282int 283delete_hierarchy(char *dir, Boolean ign_err) 284{ 285 char *cp1, *cp2; 286 287 cp1 = cp2 = dir; 288 if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir)) 289 return 1; 290 while (cp2) { 291 if ((cp2 = rindex(cp1, '/')) != NULL) 292 *cp2 = '\0'; 293 if (!isempty(dir)) 294 return 0; 295 if (vsystem("%s %s", RMDIR_CMD, dir) && ign_err) 296 return 1; 297 /* Put it back */ 298 if (cp2) { 299 *cp2 = '/'; 300 cp1 = cp2 - 1; 301 } 302 } 303 return 0; 304} 305