1 /* @(#)lcmd2.c 8.1 (Berkeley) 6/6/93 */ 2 /* $NetBSD: lcmd2.c,v 1.15 2008/12/29 01:53:35 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Edward Wang at The University of California, Berkeley. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/types.h> 37 #include <sys/time.h> 38 #include <sys/resource.h> 39 #include <string.h> 40 #include "defs.h" 41 #include "window_string.h" 42 #include "var.h" 43 #include "lcmd.h" 44 #include "alias.h" 45 46 int printalias(void *, struct var *); 47 int printvar(void *, struct var *); 48 char *strtime(struct timeval *t); 49 50 void 51 l_iostat(struct value *v __unused, struct value *a __unused) 52 { 53 struct ww *w; 54 55 if ((w = openiwin(16, "IO Statistics")) == NULL) { 56 error("Can't open statistics window: %s.", wwerror()); 57 return; 58 } 59 wwprintf(w, "ttflush\twrite\terror\tzero\tchar\n"); 60 wwprintf(w, "%d\t%d\t%d\t%d\t%d\n", 61 wwnflush, wwnwr, wwnwre, wwnwrz, wwnwrc); 62 wwprintf(w, "token\tuse\tbad\tsaving\ttotal\tbaud\n"); 63 wwprintf(w, "%d\t%d\t%d\t%d\t%d\t%d/%d (%.1f/%.1f)\n", 64 wwntokdef, wwntokuse, wwntokbad, wwntoksave, wwntokc, 65 wwntokc - wwntoksave ? 66 (int) ((float) wwbaud * wwntokc / 67 (wwntokc - wwntoksave)) : 68 wwbaud, 69 wwnwrc ? (int) ((float) wwbaud * (wwnwrc + wwntoksave) / 70 wwnwrc) : 71 wwbaud, 72 wwntokc - wwntoksave ? 73 (float) wwntokc / (wwntokc - wwntoksave) : 1.0, 74 wwnwrc ? (float) (wwnwrc + wwntoksave) / wwnwrc : 1.0); 75 wwprintf(w, "wwwrite\tattempt\tchar\n"); 76 wwprintf(w, "%d\t%d\t%d\n", 77 wwnwwr, wwnwwra, wwnwwrc); 78 wwprintf(w, "wwupdat\tline\tmiss\tscan\tclreol\tclreos\tmiss\tline\n"); 79 wwprintf(w, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", 80 wwnupdate, wwnupdline, wwnupdmiss, wwnupdscan, wwnupdclreol, 81 wwnupdclreos, wwnupdclreosmiss, wwnupdclreosline); 82 wwprintf(w, "select\terror\tzero\n"); 83 wwprintf(w, "%d\t%d\t%d\n", 84 wwnselect, wwnselecte, wwnselectz); 85 wwprintf(w, "read\terror\tzero\tchar\tack\tnack\tstat\terrorc\n"); 86 wwprintf(w, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", 87 wwnread, wwnreade, wwnreadz, wwnreadc, wwnreadack, wwnreadnack, 88 wwnreadstat, wwnreadec); 89 wwprintf(w, "ptyread\terror\tzero\tcontrol\tdata\tchar\n"); 90 wwprintf(w, "%d\t%d\t%d\t%d\t%d\t%d\n", 91 wwnwread, wwnwreade, wwnwreadz, 92 wwnwreadp, wwnwreadd, wwnwreadc); 93 waitnl(w); 94 closeiwin(w); 95 } 96 97 struct lcmd_arg arg_time[] = { 98 { "who", 1, ARG_STR }, 99 { NULL, 0, 0 } 100 }; 101 102 void 103 l_time(struct value *v __unused, struct value *a) 104 { 105 struct ww *w; 106 struct rusage rusage; 107 struct timeval timeval; 108 109 if ((w = openiwin(8, "Timing and Resource Usage")) == NULL) { 110 error("Can't open time window: %s.", wwerror()); 111 return; 112 } 113 114 (void) gettimeofday(&timeval, (struct timezone *)0); 115 timersub(&timeval, &starttime, &timeval); 116 (void) getrusage(a->v_type == V_STR 117 && str_match(a->v_str, "children", 1) 118 ? RUSAGE_CHILDREN : RUSAGE_SELF, &rusage); 119 120 wwprintf(w, "%-15s %-15s %-15s\n", 121 "time", "utime", "stime"); 122 wwprintf(w, "%-15s ", strtime(&timeval)); 123 wwprintf(w, "%-15s ", strtime(&rusage.ru_utime)); 124 wwprintf(w, "%-15s\n", strtime(&rusage.ru_stime)); 125 wwprintf(w, "%-15s %-15s %-15s %-15s\n", 126 "maxrss", "ixrss", "idrss", "isrss"); 127 wwprintf(w, "%-15ld %-15ld %-15ld %-15ld\n", 128 rusage.ru_maxrss, rusage.ru_ixrss, 129 rusage.ru_idrss, rusage.ru_isrss); 130 wwprintf(w, "%-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s\n", 131 "minflt", "majflt", "nswap", "inblk", "oublk", 132 "msgsnd", "msgrcv", "nsigs", "nvcsw", "nivcsw"); 133 wwprintf(w, "%-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld\n", 134 rusage.ru_minflt, rusage.ru_majflt, rusage.ru_nswap, 135 rusage.ru_inblock, rusage.ru_oublock, 136 rusage.ru_msgsnd, rusage.ru_msgrcv, rusage.ru_nsignals, 137 rusage.ru_nvcsw, rusage.ru_nivcsw); 138 139 waitnl(w); 140 closeiwin(w); 141 } 142 143 char * 144 strtime(struct timeval *t) 145 { 146 char fill = 0; 147 static char buf[20]; 148 char *p = buf; 149 150 if (t->tv_sec > 60*60) { 151 (void) sprintf(p, "%ld:", (long int)t->tv_sec / (60*60)); 152 while (*p++) 153 ; 154 p--; 155 t->tv_sec %= 60*60; 156 fill++; 157 } 158 if (t->tv_sec > 60) { 159 (void) sprintf(p, fill ? "%02lld:" : "%lld:", 160 (long long)t->tv_sec / 60); 161 while (*p++) 162 ; 163 p--; 164 t->tv_sec %= 60; 165 fill++; 166 } 167 (void) sprintf(p, fill ? "%02lld.%02ld" : "%lld.%02ld", 168 (long long)t->tv_sec, (long)t->tv_usec / 10000); 169 return buf; 170 } 171 172 void 173 l_list(struct value *v __unused, struct value *a __unused) 174 { 175 struct ww *w, *wp; 176 int i; 177 int n; 178 179 for (n = 0, i = 0; i < NWINDOW; i++) 180 if (window[i] != 0) 181 n++; 182 if (n == 0) { 183 error("No windows."); 184 return; 185 } 186 if ((w = openiwin(n + 2, "Windows")) == NULL) { 187 error("Can't open listing window: %s.", wwerror()); 188 return; 189 } 190 for (i = 0; i < NWINDOW; i++) { 191 if ((wp = window[i]) == NULL) 192 continue; 193 wwprintf(w, "%c %c %-13s %-.*s\n", 194 wp == selwin ? '+' : (wp == lastselwin ? '-' : ' '), 195 i + '1', 196 wp->ww_state == WWS_HASPROC ? "" : "(No process)", 197 wwncol - 20, 198 wp->ww_label ? wp->ww_label : "(No label)"); 199 } 200 waitnl(w); 201 closeiwin(w); 202 } 203 204 void 205 l_variable(struct value *v __unused, struct value *a __unused) 206 { 207 struct ww *w; 208 209 if ((w = openiwin(wwnrow - 3, "Variables")) == NULL) { 210 error("Can't open variable window: %s.", wwerror()); 211 return; 212 } 213 if (var_walk(printvar, (void *)w) >= 0) 214 waitnl(w); 215 closeiwin(w); 216 } 217 218 int 219 printvar(void *vw, struct var *r) 220 { 221 struct ww *w = vw; 222 if (more(w, 0) == 2) 223 return -1; 224 wwprintf(w, "%16s ", r->r_name); 225 switch (r->r_val.v_type) { 226 case V_STR: 227 wwprintf(w, "%s\n", r->r_val.v_str); 228 break; 229 case V_NUM: 230 wwprintf(w, "%d\n", r->r_val.v_num); 231 break; 232 case V_ERR: 233 wwprintf(w, "ERROR\n"); 234 break; 235 } 236 return 0; 237 } 238 239 struct lcmd_arg arg_def_shell[] = { 240 { "", 0, ARG_ANY|ARG_LIST }, 241 { NULL, 0, 0 } 242 }; 243 244 void 245 l_def_shell(struct value *v, struct value *a) 246 { 247 char **pp; 248 struct value *vp; 249 250 if (a->v_type == V_ERR) { 251 if ((v->v_str = str_cpy(default_shellfile)) != 0) 252 v->v_type = V_STR; 253 return; 254 } 255 if ((v->v_str = default_shellfile)) { 256 v->v_type = V_STR; 257 for (pp = default_shell + 1; *pp; pp++) { 258 str_free(*pp); 259 *pp = NULL; 260 } 261 } 262 for (pp = default_shell, vp = a; 263 vp->v_type != V_ERR && 264 pp < &default_shell[sizeof default_shell/sizeof *default_shell-1]; 265 pp++, vp++) 266 if ((*pp = vp->v_type == V_STR ? 267 str_cpy(vp->v_str) : str_itoa(vp->v_num)) == NULL) { 268 /* just leave default_shell[] the way it is */ 269 p_memerror(); 270 break; 271 } 272 if ((default_shellfile = *default_shell)) { 273 if ((*default_shell = strrchr(default_shellfile, '/'))) 274 (*default_shell)++; 275 else 276 *default_shell = default_shellfile; 277 } 278 } 279 280 struct lcmd_arg arg_alias[] = { 281 { "", 0, ARG_STR }, 282 { "", 0, ARG_STR|ARG_LIST }, 283 { NULL, 0, 0 } 284 }; 285 286 void 287 l_alias(struct value *v, struct value *a) 288 { 289 if (a->v_type == V_ERR) { 290 struct ww *w; 291 292 if ((w = openiwin(wwnrow - 3, "Aliases")) == NULL) { 293 error("Can't open alias window: %s.", wwerror()); 294 return; 295 } 296 if (alias_walk(printalias, (void *)w) >= 0) 297 waitnl(w); 298 closeiwin(w); 299 } else { 300 struct alias *ap = NULL; 301 302 if ((ap = alias_lookup(a->v_str))) { 303 if ((v->v_str = str_cpy(ap->a_buf)) == 0) { 304 p_memerror(); 305 return; 306 } 307 v->v_type = V_STR; 308 } 309 if (a[1].v_type == V_STR) { 310 struct value *vp; 311 char *p, *q; 312 char *str; 313 int n; 314 315 for (n = 0, vp = a + 1; vp->v_type != V_ERR; vp++, n++) 316 for (p = vp->v_str; *p; p++, n++) 317 ; 318 if ((str = str_alloc(n)) == NULL) { 319 p_memerror(); 320 return; 321 } 322 for (q = str, vp = a + 1; vp->v_type != V_ERR; 323 vp++, q[-1] = ' ') 324 for (p = vp->v_str; (*q++ = *p++);) 325 ; 326 q[-1] = 0; 327 if ((ap = alias_set(a[0].v_str, (char *)0)) == NULL) { 328 p_memerror(); 329 str_free(str); 330 return; 331 } 332 ap->a_buf = str; 333 } 334 } 335 } 336 337 int 338 printalias(void *vw, struct var *a) 339 { 340 struct ww *w = vw; 341 if (more(w, 0) == 2) 342 return -1; 343 wwprintf(w, "%16s %s\n", a->a_name, a->a_buf); 344 return 0; 345 } 346 347 struct lcmd_arg arg_unalias[] = { 348 { "alias", 1, ARG_STR }, 349 { NULL, 0, 0 } 350 }; 351 352 void 353 l_unalias(struct value *v, struct value *a) 354 { 355 if (a->v_type == ARG_STR) 356 v->v_num = alias_unset(a->v_str); 357 v->v_type = V_NUM; 358 } 359 360 struct lcmd_arg arg_echo[] = { 361 { "window", 1, ARG_NUM }, 362 { "", 0, ARG_ANY|ARG_LIST }, 363 { NULL, 0, 0 } 364 }; 365 366 void 367 l_echo(struct value *v __unused, struct value *a) 368 { 369 char buf[20]; 370 struct ww *w; 371 372 if ((w = vtowin(a++, selwin)) == NULL) 373 return; 374 while (a->v_type != V_ERR) { 375 if (a->v_type == V_NUM) { 376 (void) sprintf(buf, "%d", a->v_num); 377 (void) wwwrite(w, buf, strlen(buf)); 378 } else 379 (void) wwwrite(w, a->v_str, strlen(a->v_str)); 380 if ((++a)->v_type != V_ERR) 381 (void) wwwrite(w, " ", 1); 382 } 383 (void) wwwrite(w, "\r\n", 2); 384 } 385