1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 1998,2001-2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1985 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include <setjmp.h> 18*7c478bd9Sstevel@tonic-gate #include <euc.h> 19*7c478bd9Sstevel@tonic-gate #include <widec.h> 20*7c478bd9Sstevel@tonic-gate #include "restore.h" 21*7c478bd9Sstevel@tonic-gate #include <ctype.h> 22*7c478bd9Sstevel@tonic-gate #include <limits.h> 23*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate extern eucwidth_t wp; 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #define round(a, b) ((((a) + (b) - 1) / (b)) * (b)) 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Things to handle interruptions. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate static jmp_buf reset; 33*7c478bd9Sstevel@tonic-gate static int reset_OK; 34*7c478bd9Sstevel@tonic-gate static char *nextarg = NULL; 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate static int dontexpand; /* co-routine state set in getnext, used in expandarg */ 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 39*7c478bd9Sstevel@tonic-gate static void getcmd(char *, char *, size_t, char *, size_t, struct arglist *); 40*7c478bd9Sstevel@tonic-gate static void expandarg(char *, struct arglist *); 41*7c478bd9Sstevel@tonic-gate static void printlist(char *, ino_t, char *, int); 42*7c478bd9Sstevel@tonic-gate static void formatf(struct arglist *); 43*7c478bd9Sstevel@tonic-gate static char *copynext(char *, char *, size_t); 44*7c478bd9Sstevel@tonic-gate static int fcmp(struct afile *, struct afile *); 45*7c478bd9Sstevel@tonic-gate static char *fmtentry(struct afile *); 46*7c478bd9Sstevel@tonic-gate static void setpagercmd(void); 47*7c478bd9Sstevel@tonic-gate static uint_t setpagerargs(char **); 48*7c478bd9Sstevel@tonic-gate #else 49*7c478bd9Sstevel@tonic-gate static void getcmd(); 50*7c478bd9Sstevel@tonic-gate static void expandarg(); 51*7c478bd9Sstevel@tonic-gate static void printlist(); 52*7c478bd9Sstevel@tonic-gate static void formatf(); 53*7c478bd9Sstevel@tonic-gate static char *copynext(); 54*7c478bd9Sstevel@tonic-gate static int fcmp(); 55*7c478bd9Sstevel@tonic-gate static char *fmtentry(); 56*7c478bd9Sstevel@tonic-gate static void setpagercmd(); 57*7c478bd9Sstevel@tonic-gate static uint_t setpagerargs(); 58*7c478bd9Sstevel@tonic-gate #endif 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* 61*7c478bd9Sstevel@tonic-gate * Read and execute commands from the terminal. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate void 64*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 65*7c478bd9Sstevel@tonic-gate runcmdshell(void) 66*7c478bd9Sstevel@tonic-gate #else 67*7c478bd9Sstevel@tonic-gate runcmdshell() 68*7c478bd9Sstevel@tonic-gate #endif 69*7c478bd9Sstevel@tonic-gate { 70*7c478bd9Sstevel@tonic-gate struct entry *np; 71*7c478bd9Sstevel@tonic-gate ino_t ino; 72*7c478bd9Sstevel@tonic-gate static struct arglist alist = { 0, 0, 0, 0, 0 }; 73*7c478bd9Sstevel@tonic-gate char curdir[MAXCOMPLEXLEN]; 74*7c478bd9Sstevel@tonic-gate char name[MAXCOMPLEXLEN]; 75*7c478bd9Sstevel@tonic-gate char cmd[BUFSIZ]; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #ifdef lint 78*7c478bd9Sstevel@tonic-gate curdir[0] = '\0'; 79*7c478bd9Sstevel@tonic-gate #endif /* lint */ 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate canon("/", curdir, sizeof (curdir)); 82*7c478bd9Sstevel@tonic-gate loop: 83*7c478bd9Sstevel@tonic-gate if (setjmp(reset) != 0) { 84*7c478bd9Sstevel@tonic-gate for (; alist.head < alist.last; alist.head++) 85*7c478bd9Sstevel@tonic-gate freename(alist.head->fname); 86*7c478bd9Sstevel@tonic-gate nextarg = NULL; 87*7c478bd9Sstevel@tonic-gate volno = 0; 88*7c478bd9Sstevel@tonic-gate goto loop; /* make sure jmpbuf is up-to-date */ 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate reset_OK = 1; 91*7c478bd9Sstevel@tonic-gate getcmd(curdir, cmd, sizeof (cmd), name, sizeof (name), &alist); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * Using strncmp() to catch unique prefixes. 95*7c478bd9Sstevel@tonic-gate */ 96*7c478bd9Sstevel@tonic-gate switch (cmd[0]) { 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * Add elements to the extraction list. 99*7c478bd9Sstevel@tonic-gate */ 100*7c478bd9Sstevel@tonic-gate case 'a': 101*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "add", strlen(cmd)) != 0) 102*7c478bd9Sstevel@tonic-gate goto bad; 103*7c478bd9Sstevel@tonic-gate if (name[0] == '\0') 104*7c478bd9Sstevel@tonic-gate break; 105*7c478bd9Sstevel@tonic-gate ino = dirlookup(name); 106*7c478bd9Sstevel@tonic-gate if (ino == 0) 107*7c478bd9Sstevel@tonic-gate break; 108*7c478bd9Sstevel@tonic-gate if (mflag) 109*7c478bd9Sstevel@tonic-gate pathcheck(name); 110*7c478bd9Sstevel@tonic-gate treescan(name, ino, addfile); 111*7c478bd9Sstevel@tonic-gate break; 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * Change working directory. 114*7c478bd9Sstevel@tonic-gate */ 115*7c478bd9Sstevel@tonic-gate case 'c': 116*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "cd", strlen(cmd)) != 0) 117*7c478bd9Sstevel@tonic-gate goto bad; 118*7c478bd9Sstevel@tonic-gate if (name[0] == '\0') 119*7c478bd9Sstevel@tonic-gate break; 120*7c478bd9Sstevel@tonic-gate ino = dirlookup(name); 121*7c478bd9Sstevel@tonic-gate if (ino == 0) 122*7c478bd9Sstevel@tonic-gate break; 123*7c478bd9Sstevel@tonic-gate if (inodetype(ino) == LEAF) { 124*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 125*7c478bd9Sstevel@tonic-gate gettext("%s: not a directory\n"), name); 126*7c478bd9Sstevel@tonic-gate break; 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* No need to canon(name), getcmd() did it for us */ 130*7c478bd9Sstevel@tonic-gate (void) strncpy(curdir, name, sizeof (curdir)); 131*7c478bd9Sstevel@tonic-gate curdir[sizeof (curdir) - 1] = '\0'; 132*7c478bd9Sstevel@tonic-gate break; 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * Delete elements from the extraction list. 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate case 'd': 137*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "delete", strlen(cmd)) != 0) 138*7c478bd9Sstevel@tonic-gate goto bad; 139*7c478bd9Sstevel@tonic-gate if (name[0] == '\0') 140*7c478bd9Sstevel@tonic-gate break; 141*7c478bd9Sstevel@tonic-gate np = lookupname(name); 142*7c478bd9Sstevel@tonic-gate if (np == NIL || (np->e_flags & NEW) == 0) { 143*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 144*7c478bd9Sstevel@tonic-gate gettext("%s: not on extraction list\n"), name); 145*7c478bd9Sstevel@tonic-gate break; 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate treescan(name, np->e_ino, deletefile); 148*7c478bd9Sstevel@tonic-gate break; 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * Extract the requested list. 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate case 'e': 153*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "extract", strlen(cmd)) != 0) 154*7c478bd9Sstevel@tonic-gate goto bad; 155*7c478bd9Sstevel@tonic-gate attrscan(0, addfile); 156*7c478bd9Sstevel@tonic-gate createfiles(); 157*7c478bd9Sstevel@tonic-gate createlinks(); 158*7c478bd9Sstevel@tonic-gate setdirmodes(); 159*7c478bd9Sstevel@tonic-gate if (dflag) 160*7c478bd9Sstevel@tonic-gate checkrestore(); 161*7c478bd9Sstevel@tonic-gate volno = 0; 162*7c478bd9Sstevel@tonic-gate break; 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * List available commands. 165*7c478bd9Sstevel@tonic-gate */ 166*7c478bd9Sstevel@tonic-gate case 'h': 167*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "help", strlen(cmd)) != 0) 168*7c478bd9Sstevel@tonic-gate goto bad; 169*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 170*7c478bd9Sstevel@tonic-gate case '?': 171*7c478bd9Sstevel@tonic-gate /* ANSI string catenation, to shut cstyle up */ 172*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s", 173*7c478bd9Sstevel@tonic-gate gettext("Available commands are:\n" 174*7c478bd9Sstevel@tonic-gate "\tls [arg] - list directory\n" 175*7c478bd9Sstevel@tonic-gate "\tmarked [arg] - list items marked for extraction from directory\n" 176*7c478bd9Sstevel@tonic-gate "\tcd arg - change directory\n" 177*7c478bd9Sstevel@tonic-gate "\tpwd - print current directory\n" 178*7c478bd9Sstevel@tonic-gate "\tadd [arg] - add `arg' to list of files to be extracted\n" 179*7c478bd9Sstevel@tonic-gate "\tdelete [arg] - delete `arg' from list of files to be extracted\n" 180*7c478bd9Sstevel@tonic-gate "\textract - extract requested files\n" 181*7c478bd9Sstevel@tonic-gate "\tsetmodes - set modes of requested directories\n" 182*7c478bd9Sstevel@tonic-gate "\tquit - immediately exit program\n" 183*7c478bd9Sstevel@tonic-gate "\twhat - list dump header information\n" 184*7c478bd9Sstevel@tonic-gate "\tverbose - toggle verbose flag (useful with ``ls'')\n" 185*7c478bd9Sstevel@tonic-gate "\tpaginate - toggle pagination flag (affects ``ls'' and ``marked'')\n" 186*7c478bd9Sstevel@tonic-gate "\tsetpager - set pagination command and arguments\n" 187*7c478bd9Sstevel@tonic-gate "\thelp or `?' - print this list\n" 188*7c478bd9Sstevel@tonic-gate "If no `arg' is supplied, the current directory is used\n")); 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * List a directory. 192*7c478bd9Sstevel@tonic-gate */ 193*7c478bd9Sstevel@tonic-gate case 'l': 194*7c478bd9Sstevel@tonic-gate case 'm': 195*7c478bd9Sstevel@tonic-gate if ((strncmp(cmd, "ls", strlen(cmd)) != 0) && 196*7c478bd9Sstevel@tonic-gate (strncmp(cmd, "marked", strlen(cmd)) != 0)) 197*7c478bd9Sstevel@tonic-gate goto bad; 198*7c478bd9Sstevel@tonic-gate if (name[0] == '\0') 199*7c478bd9Sstevel@tonic-gate break; 200*7c478bd9Sstevel@tonic-gate ino = dirlookup(name); 201*7c478bd9Sstevel@tonic-gate if (ino == 0) 202*7c478bd9Sstevel@tonic-gate break; 203*7c478bd9Sstevel@tonic-gate printlist(name, ino, curdir, *cmd == 'm'); 204*7c478bd9Sstevel@tonic-gate break; 205*7c478bd9Sstevel@tonic-gate /* 206*7c478bd9Sstevel@tonic-gate * Print current directory or enable pagination. 207*7c478bd9Sstevel@tonic-gate */ 208*7c478bd9Sstevel@tonic-gate case 'p': 209*7c478bd9Sstevel@tonic-gate if (strlen(cmd) < 2) 210*7c478bd9Sstevel@tonic-gate goto ambiguous; 211*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "pwd", strlen(cmd)) == 0) { 212*7c478bd9Sstevel@tonic-gate if (curdir[1] == '\0') { 213*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "/\n"); 214*7c478bd9Sstevel@tonic-gate } else { 215*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", &curdir[1]); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate } else if (strncmp(cmd, "paginate", strlen(cmd)) == 0) { 218*7c478bd9Sstevel@tonic-gate if (paginating) { 219*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 220*7c478bd9Sstevel@tonic-gate gettext("paging disabled\n")); 221*7c478bd9Sstevel@tonic-gate paginating = 0; 222*7c478bd9Sstevel@tonic-gate break; 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate if (vflag) { 225*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 226*7c478bd9Sstevel@tonic-gate gettext("paging enabled (%s)\n"), 227*7c478bd9Sstevel@tonic-gate pager_catenated); 228*7c478bd9Sstevel@tonic-gate } else { 229*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 230*7c478bd9Sstevel@tonic-gate gettext("paging enabled\n")); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate if (dflag) { 233*7c478bd9Sstevel@tonic-gate int index = 0; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate while (index < pager_len) { 236*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 237*7c478bd9Sstevel@tonic-gate ">>>pager_vector[%d] = `%s'\n", 238*7c478bd9Sstevel@tonic-gate index, 239*7c478bd9Sstevel@tonic-gate pager_vector[index] ? 240*7c478bd9Sstevel@tonic-gate pager_vector[index] : "(null)"); 241*7c478bd9Sstevel@tonic-gate index += 1; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate paginating = 1; 245*7c478bd9Sstevel@tonic-gate } else { 246*7c478bd9Sstevel@tonic-gate goto bad; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate break; 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * Quit. 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate case 'q': 253*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "quit", strlen(cmd)) != 0) 254*7c478bd9Sstevel@tonic-gate goto bad; 255*7c478bd9Sstevel@tonic-gate reset_OK = 0; 256*7c478bd9Sstevel@tonic-gate return; 257*7c478bd9Sstevel@tonic-gate case 'x': 258*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "xit", strlen(cmd)) != 0) 259*7c478bd9Sstevel@tonic-gate goto bad; 260*7c478bd9Sstevel@tonic-gate reset_OK = 0; 261*7c478bd9Sstevel@tonic-gate return; 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * Toggle verbose mode. 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate case 'v': 266*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "verbose", strlen(cmd)) != 0) 267*7c478bd9Sstevel@tonic-gate goto bad; 268*7c478bd9Sstevel@tonic-gate if (vflag) { 269*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("verbose mode off\n")); 270*7c478bd9Sstevel@tonic-gate vflag = 0; 271*7c478bd9Sstevel@tonic-gate break; 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("verbose mode on\n")); 274*7c478bd9Sstevel@tonic-gate vflag = 1; 275*7c478bd9Sstevel@tonic-gate break; 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * Just restore requested directory modes, or set pagination command. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate case 's': 280*7c478bd9Sstevel@tonic-gate if (strlen(cmd) < 4) 281*7c478bd9Sstevel@tonic-gate goto ambiguous; 282*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "setmodes", strlen(cmd)) == 0) { 283*7c478bd9Sstevel@tonic-gate setdirmodes(); 284*7c478bd9Sstevel@tonic-gate } else if (strncmp(cmd, "setpager", strlen(cmd)) == 0) { 285*7c478bd9Sstevel@tonic-gate setpagercmd(); 286*7c478bd9Sstevel@tonic-gate } else { 287*7c478bd9Sstevel@tonic-gate goto bad; 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate break; 290*7c478bd9Sstevel@tonic-gate /* 291*7c478bd9Sstevel@tonic-gate * Print out dump header information. 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate case 'w': 294*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "what", strlen(cmd)) != 0) 295*7c478bd9Sstevel@tonic-gate goto bad; 296*7c478bd9Sstevel@tonic-gate printdumpinfo(); 297*7c478bd9Sstevel@tonic-gate break; 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * Turn on debugging. 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate case 'D': 302*7c478bd9Sstevel@tonic-gate if (strncmp(cmd, "Debug", strlen(cmd)) != 0) 303*7c478bd9Sstevel@tonic-gate goto bad; 304*7c478bd9Sstevel@tonic-gate if (dflag) { 305*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("debugging mode off\n")); 306*7c478bd9Sstevel@tonic-gate dflag = 0; 307*7c478bd9Sstevel@tonic-gate break; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("debugging mode on\n")); 310*7c478bd9Sstevel@tonic-gate dflag++; 311*7c478bd9Sstevel@tonic-gate break; 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * Unknown command. 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate default: 316*7c478bd9Sstevel@tonic-gate bad: 317*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 318*7c478bd9Sstevel@tonic-gate gettext("%s: unknown command; type ? for help\n"), cmd); 319*7c478bd9Sstevel@tonic-gate break; 320*7c478bd9Sstevel@tonic-gate ambiguous: 321*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 322*7c478bd9Sstevel@tonic-gate gettext("%s: ambiguous command; type ? for help\n"), cmd); 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate goto loop; 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate static char input[MAXCOMPLEXLEN]; /* shared by getcmd() and setpagercmd() */ 329*7c478bd9Sstevel@tonic-gate #define rawname input /* save space by reusing input buffer */ 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* 332*7c478bd9Sstevel@tonic-gate * Read and parse an interactive command. 333*7c478bd9Sstevel@tonic-gate * The first word on the line is assigned to "cmd". If 334*7c478bd9Sstevel@tonic-gate * there are no arguments on the command line, then "curdir" 335*7c478bd9Sstevel@tonic-gate * is returned as the argument. If there are arguments 336*7c478bd9Sstevel@tonic-gate * on the line they are returned one at a time on each 337*7c478bd9Sstevel@tonic-gate * successive call to getcmd. Each argument is first assigned 338*7c478bd9Sstevel@tonic-gate * to "name". If it does not start with "/" the pathname in 339*7c478bd9Sstevel@tonic-gate * "curdir" is prepended to it. Finally "canon" is called to 340*7c478bd9Sstevel@tonic-gate * eliminate any embedded ".." components. 341*7c478bd9Sstevel@tonic-gate */ 342*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 343*7c478bd9Sstevel@tonic-gate static void 344*7c478bd9Sstevel@tonic-gate getcmd(curdir, cmd, cmdsiz, name, namesiz, ap) 345*7c478bd9Sstevel@tonic-gate char *curdir, *cmd, *name; 346*7c478bd9Sstevel@tonic-gate size_t cmdsiz, namesiz; 347*7c478bd9Sstevel@tonic-gate struct arglist *ap; 348*7c478bd9Sstevel@tonic-gate { 349*7c478bd9Sstevel@tonic-gate char *cp; 350*7c478bd9Sstevel@tonic-gate char output[MAXCOMPLEXLEN]; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Check to see if still processing arguments. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate if (ap->head != ap->last) { 356*7c478bd9Sstevel@tonic-gate (void) strncpy(name, ap->head->fname, namesiz); 357*7c478bd9Sstevel@tonic-gate name[namesiz - 1] = '\0'; 358*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 359*7c478bd9Sstevel@tonic-gate if ((strlen(name) + 2) > namesiz) { 360*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("name is too long, ignoring")); 361*7c478bd9Sstevel@tonic-gate memset(name, 0, namesiz); 362*7c478bd9Sstevel@tonic-gate } else { 363*7c478bd9Sstevel@tonic-gate name[strlen(name) + 1] = '\0'; 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate freename(ap->head->fname); 366*7c478bd9Sstevel@tonic-gate ap->head++; 367*7c478bd9Sstevel@tonic-gate return; 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate if (nextarg != NULL) 370*7c478bd9Sstevel@tonic-gate goto getnext; 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * Read a command line and trim off trailing white space. 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate readagain: 375*7c478bd9Sstevel@tonic-gate do { 376*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s > ", progname); 377*7c478bd9Sstevel@tonic-gate (void) fflush(stderr); 378*7c478bd9Sstevel@tonic-gate (void) fgets(input, sizeof (input), terminal); 379*7c478bd9Sstevel@tonic-gate } while (!feof(terminal) && input[0] == '\n'); 380*7c478bd9Sstevel@tonic-gate if (feof(terminal)) { 381*7c478bd9Sstevel@tonic-gate (void) strncpy(cmd, "quit", cmdsiz); 382*7c478bd9Sstevel@tonic-gate return; 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate /* trim off trailing white space and newline */ 385*7c478bd9Sstevel@tonic-gate for (cp = &input[strlen(input) - 2]; 386*7c478bd9Sstevel@tonic-gate cp >= &input[0] && isspace((uchar_t)*cp); 387*7c478bd9Sstevel@tonic-gate cp--) { 388*7c478bd9Sstevel@tonic-gate continue; 389*7c478bd9Sstevel@tonic-gate /*LINTED [empty loop body]*/ 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate *++cp = '\0'; 392*7c478bd9Sstevel@tonic-gate if ((strlen(input) + 2) > MAXCOMPLEXLEN) { 393*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("command is too long\n")); 394*7c478bd9Sstevel@tonic-gate goto readagain; 395*7c478bd9Sstevel@tonic-gate } else { 396*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 397*7c478bd9Sstevel@tonic-gate *(cp + 1) = '\0'; 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate if (cp == &input[0]) 401*7c478bd9Sstevel@tonic-gate goto readagain; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate /* 404*7c478bd9Sstevel@tonic-gate * Copy the command into "cmd". 405*7c478bd9Sstevel@tonic-gate */ 406*7c478bd9Sstevel@tonic-gate cp = copynext(input, cmd, cmdsiz); 407*7c478bd9Sstevel@tonic-gate ap->cmd = cmd; 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * If no argument, use curdir as the default. 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate if (*cp == '\0') { 412*7c478bd9Sstevel@tonic-gate (void) strncpy(name, curdir, namesiz); 413*7c478bd9Sstevel@tonic-gate name[namesiz - 1] = '\0'; 414*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 415*7c478bd9Sstevel@tonic-gate if ((strlen(name) + 2) > namesiz) { 416*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("name is too long, ignoring")); 417*7c478bd9Sstevel@tonic-gate memset(name, 0, namesiz); 418*7c478bd9Sstevel@tonic-gate } else { 419*7c478bd9Sstevel@tonic-gate name[strlen(name) + 1] = '\0'; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate return; 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate nextarg = cp; 424*7c478bd9Sstevel@tonic-gate /* 425*7c478bd9Sstevel@tonic-gate * Find the next argument. 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate getnext: 428*7c478bd9Sstevel@tonic-gate cp = copynext(nextarg, rawname, sizeof (rawname)); 429*7c478bd9Sstevel@tonic-gate if (*cp == '\0') 430*7c478bd9Sstevel@tonic-gate nextarg = NULL; 431*7c478bd9Sstevel@tonic-gate else 432*7c478bd9Sstevel@tonic-gate nextarg = cp; 433*7c478bd9Sstevel@tonic-gate /* 434*7c478bd9Sstevel@tonic-gate * If it an absolute pathname, canonicalize it and return it. 435*7c478bd9Sstevel@tonic-gate */ 436*7c478bd9Sstevel@tonic-gate if (rawname[0] == '/') { 437*7c478bd9Sstevel@tonic-gate canon(rawname, name, namesiz); 438*7c478bd9Sstevel@tonic-gate } else { 439*7c478bd9Sstevel@tonic-gate /* 440*7c478bd9Sstevel@tonic-gate * For relative pathnames, prepend the current directory to 441*7c478bd9Sstevel@tonic-gate * it then canonicalize and return it. 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate (void) snprintf(output, sizeof (output), "%s/%s", 444*7c478bd9Sstevel@tonic-gate curdir, rawname); 445*7c478bd9Sstevel@tonic-gate canon(output, name, namesiz); 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate expandarg(name, ap); 448*7c478bd9Sstevel@tonic-gate /* 449*7c478bd9Sstevel@tonic-gate * ap->head->fname guaranteed to be double null-terminated and 450*7c478bd9Sstevel@tonic-gate * no more than MAXCOMPLEXLEN characters long. 451*7c478bd9Sstevel@tonic-gate */ 452*7c478bd9Sstevel@tonic-gate assert(namesiz >= (MAXCOMPLEXLEN)); 453*7c478bd9Sstevel@tonic-gate (void) strcpy(name, ap->head->fname); 454*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 455*7c478bd9Sstevel@tonic-gate name[strlen(name) + 1] = '\0'; 456*7c478bd9Sstevel@tonic-gate freename(ap->head->fname); 457*7c478bd9Sstevel@tonic-gate ap->head++; 458*7c478bd9Sstevel@tonic-gate #undef rawname 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * Strip off the next token of the input. 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate static char * 465*7c478bd9Sstevel@tonic-gate copynext(input, output, outsize) 466*7c478bd9Sstevel@tonic-gate char *input, *output; 467*7c478bd9Sstevel@tonic-gate size_t outsize; 468*7c478bd9Sstevel@tonic-gate { 469*7c478bd9Sstevel@tonic-gate char *cp, *bp, *limit; 470*7c478bd9Sstevel@tonic-gate char quote; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate dontexpand = 0; 473*7c478bd9Sstevel@tonic-gate /* skip to argument */ 474*7c478bd9Sstevel@tonic-gate for (cp = input; *cp != '\0' && isspace((uchar_t)*cp); cp++) { 475*7c478bd9Sstevel@tonic-gate continue; 476*7c478bd9Sstevel@tonic-gate /*LINTED [empty loop body]*/ 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate bp = output; 479*7c478bd9Sstevel@tonic-gate limit = output + outsize - 1; /* -1 for the trailing \0 */ 480*7c478bd9Sstevel@tonic-gate while (!isspace((uchar_t)*cp) && *cp != '\0' && bp < limit) { 481*7c478bd9Sstevel@tonic-gate /* 482*7c478bd9Sstevel@tonic-gate * Handle back slashes. 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate if (*cp == '\\') { 485*7c478bd9Sstevel@tonic-gate if (*++cp == '\0') { 486*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 487*7c478bd9Sstevel@tonic-gate "command lines cannot be continued\n")); 488*7c478bd9Sstevel@tonic-gate continue; 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate *bp++ = *cp++; 491*7c478bd9Sstevel@tonic-gate continue; 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate /* 494*7c478bd9Sstevel@tonic-gate * The usual unquoted case. 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate if (*cp != '\'' && *cp != '"') { 497*7c478bd9Sstevel@tonic-gate *bp++ = *cp++; 498*7c478bd9Sstevel@tonic-gate continue; 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * Handle single and double quotes. 502*7c478bd9Sstevel@tonic-gate */ 503*7c478bd9Sstevel@tonic-gate quote = *cp++; 504*7c478bd9Sstevel@tonic-gate dontexpand = 1; 505*7c478bd9Sstevel@tonic-gate while (*cp != quote && *cp != '\0' && bp < limit) 506*7c478bd9Sstevel@tonic-gate *bp++ = *cp++; 507*7c478bd9Sstevel@tonic-gate if (*cp++ == '\0') { 508*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 509*7c478bd9Sstevel@tonic-gate gettext("missing %c\n"), (uchar_t)quote); 510*7c478bd9Sstevel@tonic-gate cp--; 511*7c478bd9Sstevel@tonic-gate continue; 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate *bp = '\0'; 515*7c478bd9Sstevel@tonic-gate if ((strlen(output) + 2) > outsize) { 516*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 517*7c478bd9Sstevel@tonic-gate "name is too long, ignoring")); 518*7c478bd9Sstevel@tonic-gate memset(output, 0, outsize); 519*7c478bd9Sstevel@tonic-gate } else { 520*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 521*7c478bd9Sstevel@tonic-gate *(bp + 1) = '\0'; 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate return (cp); 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate /* 527*7c478bd9Sstevel@tonic-gate * Canonicalize file names to always start with ``./'' and 528*7c478bd9Sstevel@tonic-gate * remove any imbedded "." and ".." components. 529*7c478bd9Sstevel@tonic-gate * 530*7c478bd9Sstevel@tonic-gate * The pathname "canonname" is returned double null terminated. 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate void 533*7c478bd9Sstevel@tonic-gate canon(rawname, canonname, limit) 534*7c478bd9Sstevel@tonic-gate char *rawname, *canonname; 535*7c478bd9Sstevel@tonic-gate size_t limit; 536*7c478bd9Sstevel@tonic-gate { 537*7c478bd9Sstevel@tonic-gate char *cp, *np, *prefix; 538*7c478bd9Sstevel@tonic-gate uint_t len; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate assert(limit > 3); 541*7c478bd9Sstevel@tonic-gate if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0) 542*7c478bd9Sstevel@tonic-gate prefix = ""; 543*7c478bd9Sstevel@tonic-gate else if (rawname[0] == '/') 544*7c478bd9Sstevel@tonic-gate prefix = "."; 545*7c478bd9Sstevel@tonic-gate else 546*7c478bd9Sstevel@tonic-gate prefix = "./"; 547*7c478bd9Sstevel@tonic-gate (void) snprintf(canonname, limit, "%s%s", prefix, rawname); 548*7c478bd9Sstevel@tonic-gate /* 549*7c478bd9Sstevel@tonic-gate * Eliminate multiple and trailing '/'s 550*7c478bd9Sstevel@tonic-gate */ 551*7c478bd9Sstevel@tonic-gate for (cp = np = canonname; *np != '\0'; cp++) { 552*7c478bd9Sstevel@tonic-gate *cp = *np++; 553*7c478bd9Sstevel@tonic-gate while (*cp == '/' && *np == '/') 554*7c478bd9Sstevel@tonic-gate np++; 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate *cp = '\0'; 557*7c478bd9Sstevel@tonic-gate if ((strlen(canonname) + 2) > limit) { 558*7c478bd9Sstevel@tonic-gate fprintf(stderr, 559*7c478bd9Sstevel@tonic-gate gettext("canonical name is too long, ignoring name\n")); 560*7c478bd9Sstevel@tonic-gate memset(canonname, 0, limit); 561*7c478bd9Sstevel@tonic-gate } else { 562*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 563*7c478bd9Sstevel@tonic-gate *(cp + 1) = '\0'; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate if (*--cp == '/') 567*7c478bd9Sstevel@tonic-gate *cp = '\0'; 568*7c478bd9Sstevel@tonic-gate /* 569*7c478bd9Sstevel@tonic-gate * Eliminate extraneous "." and ".." from pathnames. Uses 570*7c478bd9Sstevel@tonic-gate * memmove(), as strcpy() might do the wrong thing for these 571*7c478bd9Sstevel@tonic-gate * small overlaps. 572*7c478bd9Sstevel@tonic-gate */ 573*7c478bd9Sstevel@tonic-gate np = canonname; 574*7c478bd9Sstevel@tonic-gate while (*np != '\0') { 575*7c478bd9Sstevel@tonic-gate np++; 576*7c478bd9Sstevel@tonic-gate cp = np; 577*7c478bd9Sstevel@tonic-gate while (*np != '/' && *np != '\0') 578*7c478bd9Sstevel@tonic-gate np++; 579*7c478bd9Sstevel@tonic-gate if (np - cp == 1 && *cp == '.') { 580*7c478bd9Sstevel@tonic-gate cp--; 581*7c478bd9Sstevel@tonic-gate len = strlen(np); 582*7c478bd9Sstevel@tonic-gate (void) memmove(cp, np, len); 583*7c478bd9Sstevel@tonic-gate *(cp + len) = '\0'; 584*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 585*7c478bd9Sstevel@tonic-gate *(cp + len + 1) = '\0'; 586*7c478bd9Sstevel@tonic-gate np = cp; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate if (np - cp == 2 && strncmp(cp, "..", 2) == 0) { 589*7c478bd9Sstevel@tonic-gate cp--; 590*7c478bd9Sstevel@tonic-gate /* find beginning of name */ 591*7c478bd9Sstevel@tonic-gate while (cp > &canonname[1] && *--cp != '/') { 592*7c478bd9Sstevel@tonic-gate continue; 593*7c478bd9Sstevel@tonic-gate /*LINTED [empty loop body]*/ 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate len = strlen(np); 596*7c478bd9Sstevel@tonic-gate (void) memmove(cp, np, len); 597*7c478bd9Sstevel@tonic-gate *(cp + len) = '\0'; 598*7c478bd9Sstevel@tonic-gate /* double null terminate string */ 599*7c478bd9Sstevel@tonic-gate *(cp + len + 1) = '\0'; 600*7c478bd9Sstevel@tonic-gate np = cp; 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate /* 606*7c478bd9Sstevel@tonic-gate * globals (file name generation) 607*7c478bd9Sstevel@tonic-gate * 608*7c478bd9Sstevel@tonic-gate * "*" in params matches r.e ".*" 609*7c478bd9Sstevel@tonic-gate * "?" in params matches r.e. "." 610*7c478bd9Sstevel@tonic-gate * "[...]" in params matches character class 611*7c478bd9Sstevel@tonic-gate * "[...a-z...]" in params matches a through z. 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate static void 614*7c478bd9Sstevel@tonic-gate expandarg(arg, ap) 615*7c478bd9Sstevel@tonic-gate char *arg; 616*7c478bd9Sstevel@tonic-gate struct arglist *ap; 617*7c478bd9Sstevel@tonic-gate { 618*7c478bd9Sstevel@tonic-gate static struct afile single; 619*7c478bd9Sstevel@tonic-gate int size; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate ap->head = ap->last = (struct afile *)0; 622*7c478bd9Sstevel@tonic-gate if (dontexpand) 623*7c478bd9Sstevel@tonic-gate size = 0; 624*7c478bd9Sstevel@tonic-gate else 625*7c478bd9Sstevel@tonic-gate size = expand(arg, 0, ap); 626*7c478bd9Sstevel@tonic-gate if (size == 0) { 627*7c478bd9Sstevel@tonic-gate struct entry *ep; 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate ep = lookupname(arg); 630*7c478bd9Sstevel@tonic-gate single.fnum = ep ? ep->e_ino : 0; 631*7c478bd9Sstevel@tonic-gate single.fname = savename(arg); 632*7c478bd9Sstevel@tonic-gate ap->head = &single; 633*7c478bd9Sstevel@tonic-gate ap->last = ap->head + 1; 634*7c478bd9Sstevel@tonic-gate return; 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate if ((ap->last - ap->head) > ULONG_MAX) { 637*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 638*7c478bd9Sstevel@tonic-gate gettext("Argument expansion too large to sort\n")); 639*7c478bd9Sstevel@tonic-gate } else { 640*7c478bd9Sstevel@tonic-gate /* LINTED pointer arith just range-checked */ 641*7c478bd9Sstevel@tonic-gate qsort((char *)ap->head, (size_t)(ap->last - ap->head), 642*7c478bd9Sstevel@tonic-gate sizeof (*ap->head), 643*7c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *)) fcmp); 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate /* 648*7c478bd9Sstevel@tonic-gate * Do an "ls" style listing of a directory 649*7c478bd9Sstevel@tonic-gate */ 650*7c478bd9Sstevel@tonic-gate static void 651*7c478bd9Sstevel@tonic-gate printlist(name, ino, basename, marked_only) 652*7c478bd9Sstevel@tonic-gate char *name; 653*7c478bd9Sstevel@tonic-gate ino_t ino; 654*7c478bd9Sstevel@tonic-gate char *basename; 655*7c478bd9Sstevel@tonic-gate int marked_only; 656*7c478bd9Sstevel@tonic-gate { 657*7c478bd9Sstevel@tonic-gate struct afile *fp; 658*7c478bd9Sstevel@tonic-gate struct direct *dp; 659*7c478bd9Sstevel@tonic-gate static struct arglist alist = { 0, 0, 0, 0, "ls" }; 660*7c478bd9Sstevel@tonic-gate struct afile single; 661*7c478bd9Sstevel@tonic-gate struct entry *np; 662*7c478bd9Sstevel@tonic-gate RST_DIR *dirp; 663*7c478bd9Sstevel@tonic-gate int list_entry; 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate if ((dirp = rst_opendir(name)) == NULL) { 666*7c478bd9Sstevel@tonic-gate single.fnum = ino; 667*7c478bd9Sstevel@tonic-gate if (strncmp(name, basename, strlen(basename)) == 0) 668*7c478bd9Sstevel@tonic-gate single.fname = savename(name + strlen(basename) + 1); 669*7c478bd9Sstevel@tonic-gate else 670*7c478bd9Sstevel@tonic-gate single.fname = savename(name); 671*7c478bd9Sstevel@tonic-gate alist.head = &single; 672*7c478bd9Sstevel@tonic-gate alist.last = alist.head + 1; 673*7c478bd9Sstevel@tonic-gate if (alist.base != NULL) { 674*7c478bd9Sstevel@tonic-gate free(alist.base); 675*7c478bd9Sstevel@tonic-gate alist.base = NULL; 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate } else { 678*7c478bd9Sstevel@tonic-gate alist.head = (struct afile *)0; 679*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:\n", name); 680*7c478bd9Sstevel@tonic-gate while (dp = rst_readdir(dirp)) { 681*7c478bd9Sstevel@tonic-gate if (dp == NULL || dp->d_ino == 0) { 682*7c478bd9Sstevel@tonic-gate rst_closedir(dirp); 683*7c478bd9Sstevel@tonic-gate dirp = NULL; 684*7c478bd9Sstevel@tonic-gate break; 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate if (!dflag && BIT(dp->d_ino, dumpmap) == 0) 687*7c478bd9Sstevel@tonic-gate continue; 688*7c478bd9Sstevel@tonic-gate if (vflag == 0 && 689*7c478bd9Sstevel@tonic-gate (strcmp(dp->d_name, ".") == 0 || 690*7c478bd9Sstevel@tonic-gate strcmp(dp->d_name, "..") == 0)) 691*7c478bd9Sstevel@tonic-gate continue; 692*7c478bd9Sstevel@tonic-gate list_entry = 1; 693*7c478bd9Sstevel@tonic-gate if (marked_only) { 694*7c478bd9Sstevel@tonic-gate np = lookupino(dp->d_ino); 695*7c478bd9Sstevel@tonic-gate if ((np == NIL) || ((np->e_flags & NEW) == 0)) 696*7c478bd9Sstevel@tonic-gate list_entry = 0; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate if (list_entry) { 699*7c478bd9Sstevel@tonic-gate if (!mkentry(dp->d_name, dp->d_ino, &alist)) { 700*7c478bd9Sstevel@tonic-gate rst_closedir(dirp); 701*7c478bd9Sstevel@tonic-gate return; 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate if (alist.head != 0) { 707*7c478bd9Sstevel@tonic-gate if ((alist.last - alist.head) > ULONG_MAX) { 708*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 709*7c478bd9Sstevel@tonic-gate gettext("Directory too large to sort\n")); 710*7c478bd9Sstevel@tonic-gate } else { 711*7c478bd9Sstevel@tonic-gate qsort((char *)alist.head, 712*7c478bd9Sstevel@tonic-gate /* LINTED range-checked */ 713*7c478bd9Sstevel@tonic-gate (size_t)(alist.last - alist.head), 714*7c478bd9Sstevel@tonic-gate sizeof (*alist.head), 715*7c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *)) fcmp); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate formatf(&alist); 718*7c478bd9Sstevel@tonic-gate for (fp = alist.head; fp < alist.last; fp++) 719*7c478bd9Sstevel@tonic-gate freename(fp->fname); 720*7c478bd9Sstevel@tonic-gate alist.head = NULL; 721*7c478bd9Sstevel@tonic-gate /* 722*7c478bd9Sstevel@tonic-gate * Don't free alist.base, as we'll probably be called 723*7c478bd9Sstevel@tonic-gate * again, and might as well re-use what we've got. 724*7c478bd9Sstevel@tonic-gate */ 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate if (dirp != NULL) { 727*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 728*7c478bd9Sstevel@tonic-gate rst_closedir(dirp); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate /* 733*7c478bd9Sstevel@tonic-gate * Print out a pretty listing of a directory 734*7c478bd9Sstevel@tonic-gate */ 735*7c478bd9Sstevel@tonic-gate static void 736*7c478bd9Sstevel@tonic-gate formatf(ap) 737*7c478bd9Sstevel@tonic-gate struct arglist *ap; 738*7c478bd9Sstevel@tonic-gate { 739*7c478bd9Sstevel@tonic-gate struct afile *fp; 740*7c478bd9Sstevel@tonic-gate struct entry *np; 741*7c478bd9Sstevel@tonic-gate /* LINTED: result fits into an int */ 742*7c478bd9Sstevel@tonic-gate int nentry = (int)(ap->last - ap->head); 743*7c478bd9Sstevel@tonic-gate int i, j; 744*7c478bd9Sstevel@tonic-gate uint_t len, w, width = 0, columns, lines; 745*7c478bd9Sstevel@tonic-gate char *cp; 746*7c478bd9Sstevel@tonic-gate FILE *output = stderr; 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate if (ap->head == ap->last) 749*7c478bd9Sstevel@tonic-gate return; 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate if (paginating) { 752*7c478bd9Sstevel@tonic-gate int fds[2]; 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate if (pipe(fds) < 0) { 755*7c478bd9Sstevel@tonic-gate perror(gettext("could not create pipe")); 756*7c478bd9Sstevel@tonic-gate goto no_page; 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate switch (fork()) { 760*7c478bd9Sstevel@tonic-gate case -1: 761*7c478bd9Sstevel@tonic-gate perror(gettext("could not fork")); 762*7c478bd9Sstevel@tonic-gate goto no_page; 763*7c478bd9Sstevel@tonic-gate case 0: 764*7c478bd9Sstevel@tonic-gate /* 765*7c478bd9Sstevel@tonic-gate * Make sure final output still ends up in 766*7c478bd9Sstevel@tonic-gate * the same place. 767*7c478bd9Sstevel@tonic-gate */ 768*7c478bd9Sstevel@tonic-gate (void) dup2(fileno(stderr), fileno(stdout)); 769*7c478bd9Sstevel@tonic-gate (void) close(fds[0]); 770*7c478bd9Sstevel@tonic-gate (void) dup2(fds[1], fileno(stdin)); 771*7c478bd9Sstevel@tonic-gate execvp(pager_vector[0], pager_vector); 772*7c478bd9Sstevel@tonic-gate perror(gettext("execvp of pager failed")); 773*7c478bd9Sstevel@tonic-gate exit(1); 774*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 775*7c478bd9Sstevel@tonic-gate default: 776*7c478bd9Sstevel@tonic-gate (void) close(fds[1]); 777*7c478bd9Sstevel@tonic-gate output = fdopen(fds[0], "w"); 778*7c478bd9Sstevel@tonic-gate if (output != (FILE *)NULL) { 779*7c478bd9Sstevel@tonic-gate break; 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate perror(gettext("could not open pipe to pager")); 782*7c478bd9Sstevel@tonic-gate output = stderr; 783*7c478bd9Sstevel@tonic-gate no_page: 784*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 785*7c478bd9Sstevel@tonic-gate gettext("pagination disabled\n")); 786*7c478bd9Sstevel@tonic-gate paginating = 0; 787*7c478bd9Sstevel@tonic-gate } 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate for (fp = ap->head; fp < ap->last; fp++) { 791*7c478bd9Sstevel@tonic-gate fp->ftype = inodetype(fp->fnum); 792*7c478bd9Sstevel@tonic-gate np = lookupino(fp->fnum); 793*7c478bd9Sstevel@tonic-gate if (np != NIL) 794*7c478bd9Sstevel@tonic-gate fp->fflags = np->e_flags; 795*7c478bd9Sstevel@tonic-gate else 796*7c478bd9Sstevel@tonic-gate fp->fflags = 0; 797*7c478bd9Sstevel@tonic-gate len = strlen(fmtentry(fp)); 798*7c478bd9Sstevel@tonic-gate if (len > width) 799*7c478bd9Sstevel@tonic-gate width = len; 800*7c478bd9Sstevel@tonic-gate } 801*7c478bd9Sstevel@tonic-gate width += 2; 802*7c478bd9Sstevel@tonic-gate columns = 80 / width; 803*7c478bd9Sstevel@tonic-gate if (columns == 0) 804*7c478bd9Sstevel@tonic-gate columns = 1; 805*7c478bd9Sstevel@tonic-gate lines = (nentry + columns - 1) / columns; 806*7c478bd9Sstevel@tonic-gate for (i = 0; i < lines && !ferror(output); i++) { 807*7c478bd9Sstevel@tonic-gate for (j = 0; j < columns && !ferror(output); j++) { 808*7c478bd9Sstevel@tonic-gate fp = ap->head + j * lines + i; 809*7c478bd9Sstevel@tonic-gate cp = fmtentry(fp); 810*7c478bd9Sstevel@tonic-gate (void) fprintf(output, "%s", cp); 811*7c478bd9Sstevel@tonic-gate if (fp + lines >= ap->last) { 812*7c478bd9Sstevel@tonic-gate (void) fprintf(output, "\n"); 813*7c478bd9Sstevel@tonic-gate break; 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate w = strlen(cp); 816*7c478bd9Sstevel@tonic-gate while (w < width) { 817*7c478bd9Sstevel@tonic-gate w++; 818*7c478bd9Sstevel@tonic-gate if (fprintf(output, " ") < 0) 819*7c478bd9Sstevel@tonic-gate break; 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate } 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate if (paginating) { 825*7c478bd9Sstevel@tonic-gate (void) fclose(output); 826*7c478bd9Sstevel@tonic-gate (void) wait((int *)NULL); 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * Comparison routine for qsort. 832*7c478bd9Sstevel@tonic-gate */ 833*7c478bd9Sstevel@tonic-gate static int 834*7c478bd9Sstevel@tonic-gate fcmp(f1, f2) 835*7c478bd9Sstevel@tonic-gate struct afile *f1, *f2; 836*7c478bd9Sstevel@tonic-gate { 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate return (strcoll(f1->fname, f2->fname)); 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate /* 842*7c478bd9Sstevel@tonic-gate * Format a directory entry. 843*7c478bd9Sstevel@tonic-gate */ 844*7c478bd9Sstevel@tonic-gate static char * 845*7c478bd9Sstevel@tonic-gate fmtentry(fp) 846*7c478bd9Sstevel@tonic-gate struct afile *fp; 847*7c478bd9Sstevel@tonic-gate { 848*7c478bd9Sstevel@tonic-gate static char fmtres[MAXCOMPLEXLEN]; 849*7c478bd9Sstevel@tonic-gate static int precision = 0; 850*7c478bd9Sstevel@tonic-gate ino_t i; 851*7c478bd9Sstevel@tonic-gate char *cp, *dp, *limit; 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate if (!vflag) { 854*7c478bd9Sstevel@tonic-gate /* MAXCOMPLEXLEN assumed to be >= 1 */ 855*7c478bd9Sstevel@tonic-gate fmtres[0] = '\0'; 856*7c478bd9Sstevel@tonic-gate } else { 857*7c478bd9Sstevel@tonic-gate if (precision == 0) { 858*7c478bd9Sstevel@tonic-gate for (i = maxino; i != 0; i /= 10) 859*7c478bd9Sstevel@tonic-gate precision++; 860*7c478bd9Sstevel@tonic-gate if (sizeof (fmtres) < (unsigned)(precision + 2)) { 861*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 862*7c478bd9Sstevel@tonic-gate "\nInternal check failed, minimum width %d exceeds available size %d\n"), 863*7c478bd9Sstevel@tonic-gate (precision + 2), sizeof (fmtres)); 864*7c478bd9Sstevel@tonic-gate done(1); 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate (void) snprintf(fmtres, sizeof (fmtres), "%*ld ", 868*7c478bd9Sstevel@tonic-gate precision, fp->fnum); 869*7c478bd9Sstevel@tonic-gate } 870*7c478bd9Sstevel@tonic-gate dp = &fmtres[strlen(fmtres)]; 871*7c478bd9Sstevel@tonic-gate limit = fmtres + sizeof (fmtres) - 1; 872*7c478bd9Sstevel@tonic-gate if (dflag && BIT(fp->fnum, dumpmap) == 0) 873*7c478bd9Sstevel@tonic-gate *dp++ = '^'; 874*7c478bd9Sstevel@tonic-gate else if ((fp->fflags & NEW) != 0) 875*7c478bd9Sstevel@tonic-gate *dp++ = '*'; 876*7c478bd9Sstevel@tonic-gate else 877*7c478bd9Sstevel@tonic-gate *dp++ = ' '; 878*7c478bd9Sstevel@tonic-gate for (cp = fp->fname; *cp && dp < limit; cp++) 879*7c478bd9Sstevel@tonic-gate /* LINTED: precedence ok, can't fix system macro */ 880*7c478bd9Sstevel@tonic-gate if (!vflag && (!ISPRINT(*cp, wp))) 881*7c478bd9Sstevel@tonic-gate *dp++ = '?'; 882*7c478bd9Sstevel@tonic-gate else 883*7c478bd9Sstevel@tonic-gate *dp++ = *cp; 884*7c478bd9Sstevel@tonic-gate if (fp->ftype == NODE && dp < limit) 885*7c478bd9Sstevel@tonic-gate *dp++ = '/'; 886*7c478bd9Sstevel@tonic-gate *dp++ = 0; 887*7c478bd9Sstevel@tonic-gate return (fmtres); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate /* 891*7c478bd9Sstevel@tonic-gate * respond to interrupts 892*7c478bd9Sstevel@tonic-gate */ 893*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 894*7c478bd9Sstevel@tonic-gate void 895*7c478bd9Sstevel@tonic-gate onintr(sig) 896*7c478bd9Sstevel@tonic-gate int sig; 897*7c478bd9Sstevel@tonic-gate { 898*7c478bd9Sstevel@tonic-gate char buf[300]; 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate if (command == 'i' && reset_OK) 901*7c478bd9Sstevel@tonic-gate longjmp(reset, 1); 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 904*7c478bd9Sstevel@tonic-gate gettext("%s interrupted, continue"), progname); 905*7c478bd9Sstevel@tonic-gate if (reply(buf) == FAIL) 906*7c478bd9Sstevel@tonic-gate done(1); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate /* 909*7c478bd9Sstevel@tonic-gate * Set up pager_catenated and pager_vector. 910*7c478bd9Sstevel@tonic-gate */ 911*7c478bd9Sstevel@tonic-gate void 912*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 913*7c478bd9Sstevel@tonic-gate initpagercmd(void) 914*7c478bd9Sstevel@tonic-gate #else 915*7c478bd9Sstevel@tonic-gate initpagercmd() 916*7c478bd9Sstevel@tonic-gate #endif 917*7c478bd9Sstevel@tonic-gate { 918*7c478bd9Sstevel@tonic-gate char *cp; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate cp = getenv("PAGER"); 921*7c478bd9Sstevel@tonic-gate if (cp != NULL) 922*7c478bd9Sstevel@tonic-gate pager_catenated = strdup(cp); 923*7c478bd9Sstevel@tonic-gate if ((pager_catenated == NULL) || (*pager_catenated == '\0')) { 924*7c478bd9Sstevel@tonic-gate if (pager_catenated != NULL) 925*7c478bd9Sstevel@tonic-gate free(pager_catenated); 926*7c478bd9Sstevel@tonic-gate pager_catenated = strdup(DEF_PAGER); 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate if (pager_catenated == NULL) { 929*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 930*7c478bd9Sstevel@tonic-gate done(1); 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate pager_vector = (char **)malloc(sizeof (char *)); 934*7c478bd9Sstevel@tonic-gate if (pager_vector == NULL) { 935*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 936*7c478bd9Sstevel@tonic-gate done(1); 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate pager_len = 1; 940*7c478bd9Sstevel@tonic-gate cp = pager_catenated; 941*7c478bd9Sstevel@tonic-gate (void) setpagerargs(&cp); 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate /* 946*7c478bd9Sstevel@tonic-gate * Resets pager_catenated and pager_vector from user input. 947*7c478bd9Sstevel@tonic-gate */ 948*7c478bd9Sstevel@tonic-gate void 949*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 950*7c478bd9Sstevel@tonic-gate setpagercmd(void) 951*7c478bd9Sstevel@tonic-gate #else 952*7c478bd9Sstevel@tonic-gate setpagercmd() 953*7c478bd9Sstevel@tonic-gate #endif 954*7c478bd9Sstevel@tonic-gate { 955*7c478bd9Sstevel@tonic-gate uint_t catenate_length; 956*7c478bd9Sstevel@tonic-gate int index; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate /* 959*7c478bd9Sstevel@tonic-gate * We'll get called immediately after setting a pager, due to 960*7c478bd9Sstevel@tonic-gate * our interaction with getcmd()'s internal state. Don't do 961*7c478bd9Sstevel@tonic-gate * anything when that happens. 962*7c478bd9Sstevel@tonic-gate */ 963*7c478bd9Sstevel@tonic-gate if (*input == '\0') 964*7c478bd9Sstevel@tonic-gate return; 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate if (pager_len > 0) { 967*7c478bd9Sstevel@tonic-gate for (index = 0; pager_vector[index] != (char *)NULL; index += 1) 968*7c478bd9Sstevel@tonic-gate free(pager_vector[index]); 969*7c478bd9Sstevel@tonic-gate free(pager_vector); 970*7c478bd9Sstevel@tonic-gate free(pager_catenated); 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate pager_vector = (char **)malloc(2 * sizeof (char *)); 974*7c478bd9Sstevel@tonic-gate if (pager_vector == NULL) { 975*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 976*7c478bd9Sstevel@tonic-gate done(1); 977*7c478bd9Sstevel@tonic-gate } 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate pager_len = 2; 980*7c478bd9Sstevel@tonic-gate pager_vector[0] = strdup(input); 981*7c478bd9Sstevel@tonic-gate if (pager_vector[0] == NULL) { 982*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 983*7c478bd9Sstevel@tonic-gate done(1); 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate if (dflag) 986*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("got command `%s'\n"), input); 987*7c478bd9Sstevel@tonic-gate catenate_length = setpagerargs(&nextarg) + strlen(pager_vector[0]) + 1; 988*7c478bd9Sstevel@tonic-gate pager_catenated = (char *)malloc(catenate_length * 989*7c478bd9Sstevel@tonic-gate (size_t)sizeof (char)); 990*7c478bd9Sstevel@tonic-gate if (pager_catenated == (char *)NULL) { 991*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 992*7c478bd9Sstevel@tonic-gate done(1); 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate for (index = 0; pager_vector[index] != (char *)NULL; index += 1) { 995*7c478bd9Sstevel@tonic-gate if (index > 0) 996*7c478bd9Sstevel@tonic-gate (void) strcat(pager_catenated, " "); 997*7c478bd9Sstevel@tonic-gate (void) strcat(pager_catenated, pager_vector[index]); 998*7c478bd9Sstevel@tonic-gate } 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate /* 1003*7c478bd9Sstevel@tonic-gate * Extract arguments for the pager command from getcmd()'s input buffer. 1004*7c478bd9Sstevel@tonic-gate */ 1005*7c478bd9Sstevel@tonic-gate static uint_t 1006*7c478bd9Sstevel@tonic-gate setpagerargs(source) 1007*7c478bd9Sstevel@tonic-gate char **source; 1008*7c478bd9Sstevel@tonic-gate { 1009*7c478bd9Sstevel@tonic-gate char word[MAXCOMPLEXLEN]; 1010*7c478bd9Sstevel@tonic-gate char *cp = *source; 1011*7c478bd9Sstevel@tonic-gate uint_t length = 0; 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate while ((cp != (char *)NULL) && (*cp != '\0')) { 1014*7c478bd9Sstevel@tonic-gate cp = copynext(cp, word, sizeof (word)); 1015*7c478bd9Sstevel@tonic-gate if (dflag) 1016*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("got word `%s'\n"), word); 1017*7c478bd9Sstevel@tonic-gate pager_vector = (char **)realloc(pager_vector, 1018*7c478bd9Sstevel@tonic-gate (size_t)sizeof (char *) * (pager_len + 1)); 1019*7c478bd9Sstevel@tonic-gate if (pager_vector == (char **)NULL) { 1020*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 1021*7c478bd9Sstevel@tonic-gate done(1); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate pager_vector[pager_len - 1] = strdup(word); 1024*7c478bd9Sstevel@tonic-gate if (pager_vector[pager_len - 1] == (char *)NULL) { 1025*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 1026*7c478bd9Sstevel@tonic-gate done(1); 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate length += strlen(word) + 1; 1029*7c478bd9Sstevel@tonic-gate pager_len += 1; 1030*7c478bd9Sstevel@tonic-gate } 1031*7c478bd9Sstevel@tonic-gate pager_vector[pager_len - 1] = (char *)NULL; 1032*7c478bd9Sstevel@tonic-gate *source = cp; 1033*7c478bd9Sstevel@tonic-gate return (length); 1034*7c478bd9Sstevel@tonic-gate } 1035